summaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/armksyms.c4
-rw-r--r--arch/arm/kernel/arthur.c2
-rw-r--r--arch/arm/kernel/bios32.c1
-rw-r--r--arch/arm/kernel/dma-footbridge.c1
-rw-r--r--arch/arm/kernel/dma-rpc.c1
-rw-r--r--arch/arm/kernel/dma.c2
-rw-r--r--arch/arm/kernel/ecard.c10
-rw-r--r--arch/arm/kernel/hw-footbridge.c145
-rw-r--r--arch/arm/kernel/hw-sa1100.c2
-rw-r--r--arch/arm/kernel/irq.c2
-rw-r--r--arch/arm/kernel/isa.c1
-rw-r--r--arch/arm/kernel/leds-footbridge.c2
-rw-r--r--arch/arm/kernel/leds-sa1100.c2
-rw-r--r--arch/arm/kernel/process.c10
-rw-r--r--arch/arm/kernel/ptrace.c571
-rw-r--r--arch/arm/kernel/ptrace.h16
-rw-r--r--arch/arm/kernel/semaphore.c1
-rw-r--r--arch/arm/kernel/setup.c1
-rw-r--r--arch/arm/kernel/signal.c23
-rw-r--r--arch/arm/kernel/time.c1
-rw-r--r--arch/arm/kernel/traps.c126
21 files changed, 482 insertions, 442 deletions
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index ffd0f1b5e..5ac0743be 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -31,6 +31,8 @@ extern void outswb(unsigned int port, const void *to, int len);
extern unsigned int local_bh_count[NR_CPUS];
extern unsigned int local_irq_count[NR_CPUS];
+extern void __bad_xchg(volatile void *ptr, int size);
+
/*
* syscalls
*/
@@ -90,7 +92,6 @@ EXPORT_SYMBOL(kd_mksound);
EXPORT_SYMBOL(dump_thread);
EXPORT_SYMBOL(dump_fpu);
EXPORT_SYMBOL(udelay);
-EXPORT_SYMBOL(xchg_str);
EXPORT_SYMBOL(local_bh_count);
EXPORT_SYMBOL(local_irq_count);
#ifdef CONFIG_CPU_32
@@ -103,6 +104,7 @@ EXPORT_SYMBOL(system_serial_low);
EXPORT_SYMBOL(system_serial_high);
EXPORT_SYMBOL(mem_fclk_21285);
EXPORT_SYMBOL(__bug);
+EXPORT_SYMBOL(__bad_xchg);
EXPORT_SYMBOL(__readwrite_bug);
EXPORT_SYMBOL(enable_irq);
EXPORT_SYMBOL(disable_irq);
diff --git a/arch/arm/kernel/arthur.c b/arch/arm/kernel/arthur.c
index 8a8a5510d..0547302f8 100644
--- a/arch/arm/kernel/arthur.c
+++ b/arch/arm/kernel/arthur.c
@@ -3,8 +3,8 @@
* Copyright (C) 1998-1999 Philip Blundell
*/
-#include <linux/personality.h>
#include <linux/module.h>
+#include <linux/personality.h>
#include <linux/stddef.h>
#include <linux/signal.h>
#include <linux/sched.h>
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index 2fbda24be..a077f13b9 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -8,7 +8,6 @@
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/pci.h>
-#include <linux/errno.h>
#include <linux/init.h>
#include <asm/irq.h>
diff --git a/arch/arm/kernel/dma-footbridge.c b/arch/arm/kernel/dma-footbridge.c
index 65875831c..1d2ef26c4 100644
--- a/arch/arm/kernel/dma-footbridge.c
+++ b/arch/arm/kernel/dma-footbridge.c
@@ -13,7 +13,6 @@
#include <linux/config.h>
#include <linux/sched.h>
-#include <linux/errno.h>
#include <linux/init.h>
#include <asm/dma.h>
diff --git a/arch/arm/kernel/dma-rpc.c b/arch/arm/kernel/dma-rpc.c
index e1b54233b..f4bc97f1d 100644
--- a/arch/arm/kernel/dma-rpc.c
+++ b/arch/arm/kernel/dma-rpc.c
@@ -15,6 +15,7 @@
#include <asm/fiq.h>
#include <asm/io.h>
#include <asm/iomd.h>
+#include <asm/irq.h>
#include <asm/hardware.h>
#include <asm/uaccess.h>
diff --git a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c
index 7d1a11cd5..ff8322d34 100644
--- a/arch/arm/kernel/dma.c
+++ b/arch/arm/kernel/dma.c
@@ -14,9 +14,9 @@
*
* Moved DMA resource allocation here...
*/
+#include <linux/malloc.h>
#include <linux/sched.h>
#include <linux/module.h>
-#include <linux/malloc.h>
#include <linux/mman.h>
#include <linux/init.h>
#include <linux/spinlock.h>
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index 61eb422b2..b4d38e00f 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -33,9 +33,7 @@
#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/malloc.h>
-#include <linux/errno.h>
#include <linux/proc_fs.h>
-#include <linux/unistd.h>
#include <linux/init.h>
#include <asm/dma.h>
@@ -913,7 +911,6 @@ ecard_probe(int slot, card_type_t type)
ecard_t **ecp;
ecard_t *ec;
struct ex_ecid cid;
- char buffer[200];
int i, rc = -ENOMEM;
ec = kmalloc(sizeof(ecard_t), GFP_KERNEL);
@@ -994,12 +991,9 @@ ecard_probe(int slot, card_type_t type)
nodev:
if (rc && ec)
kfree(ec);
- else {
+ else
slot_to_expcard[slot] = ec;
- ecard_prints(buffer, ec);
- printk("%s", buffer);
- }
return rc;
}
@@ -1075,7 +1069,7 @@ void __init ecard_init(void)
init_waitqueue_head(&ecard_done);
#endif
- printk("Probing expansion cards: (does not imply support)\n");
+ printk("Probing expansion cards\n");
for (slot = 0; slot < 8; slot ++) {
if (ecard_probe(slot, ECARD_EASI) == -ENODEV)
diff --git a/arch/arm/kernel/hw-footbridge.c b/arch/arm/kernel/hw-footbridge.c
index 08aac078e..b56b944e7 100644
--- a/arch/arm/kernel/hw-footbridge.c
+++ b/arch/arm/kernel/hw-footbridge.c
@@ -8,19 +8,12 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/sched.h>
+#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/ptrace.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/smp.h>
-#include <linux/mm.h>
#include <linux/init.h>
-#include <asm/dec21285.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include <asm/leds.h>
#include <asm/system.h>
@@ -28,6 +21,13 @@
#define GP1_IO_BASE 0x338
#define GP2_IO_BASE 0x33a
+
+#ifdef CONFIG_LEDS
+#define DEFAULT_LEDS 0
+#else
+#define DEFAULT_LEDS GPIO_GREEN_LED
+#endif
+
/*
* Netwinder stuff
*/
@@ -396,9 +396,9 @@ static unsigned char rwa_unlock[] __initdata =
0x3a, 0x9d, 0xce, 0xe7, 0x73, 0x39 };
#ifndef DEBUG
-#define dprintk if (0) printk
+#define dprintk(x...)
#else
-#define dprintk printk
+#define dprintk(x...) printk(x)
#endif
#define WRITE_RWA(r,v) do { outb((r), 0x279); udelay(10); outb((v), 0xa79); } while (0)
@@ -602,74 +602,13 @@ EXPORT_SYMBOL(gpio_modify_op);
EXPORT_SYMBOL(gpio_modify_io);
EXPORT_SYMBOL(cpld_modify);
-#endif
-
-#ifdef CONFIG_LEDS
-#define DEFAULT_LEDS 0
-#else
-#define DEFAULT_LEDS GPIO_GREEN_LED
-#endif
-
-/*
- * CATS stuff
- */
-#ifdef CONFIG_ARCH_CATS
-
-#define CONFIG_PORT 0x370
-#define INDEX_PORT (CONFIG_PORT)
-#define DATA_PORT (CONFIG_PORT + 1)
-
-static void __init cats_hw_init(void)
-{
- /* Set Aladdin to CONFIGURE mode */
- outb(0x51, CONFIG_PORT);
- outb(0x23, CONFIG_PORT);
-
- /* Select logical device 3 */
- outb(0x07, INDEX_PORT);
- outb(0x03, DATA_PORT);
-
- /* Set parallel port to DMA channel 3, ECP+EPP1.9,
- enable EPP timeout */
- outb(0x74, INDEX_PORT);
- outb(0x03, DATA_PORT);
-
- outb(0xf0, INDEX_PORT);
- outb(0x0f, DATA_PORT);
-
- outb(0xf1, INDEX_PORT);
- outb(0x07, DATA_PORT);
-
- /* Select logical device 4 */
- outb(0x07, INDEX_PORT);
- outb(0x04, DATA_PORT);
-
- /* UART1 high speed mode */
- outb(0xf0, INDEX_PORT);
- outb(0x02, DATA_PORT);
-
- /* Select logical device 5 */
- outb(0x07, INDEX_PORT);
- outb(0x05, DATA_PORT);
-
- /* UART2 high speed mode */
- outb(0xf0, INDEX_PORT);
- outb(0x02, DATA_PORT);
-
- /* Set Aladdin to RUN mode */
- outb(0xbb, CONFIG_PORT);
-}
-
-#endif
-
/*
* Initialise any other hardware after we've got the PCI bus
* initialised. We may need the PCI bus to talk to this other
* hardware.
*/
-static int __init hw_init(void)
+static int __init nw_hw_init(void)
{
-#ifdef CONFIG_ARCH_NETWINDER
/*
* this ought to have a better home...
* Since this calls the above routines, which are
@@ -688,12 +627,66 @@ static int __init hw_init(void)
gpio_modify_op(GPIO_RED_LED|GPIO_GREEN_LED, DEFAULT_LEDS);
spin_unlock_irqrestore(&gpio_lock, flags);
}
+ return 0;
+}
+
+__initcall(nw_hw_init);
#endif
+
+/*
+ * CATS stuff
+ */
#ifdef CONFIG_ARCH_CATS
- if (machine_is_cats())
- cats_hw_init();
-#endif
+
+#define CONFIG_PORT 0x370
+#define INDEX_PORT (CONFIG_PORT)
+#define DATA_PORT (CONFIG_PORT + 1)
+
+static int __init cats_hw_init(void)
+{
+ if (machine_is_cats()) {
+ /* Set Aladdin to CONFIGURE mode */
+ outb(0x51, CONFIG_PORT);
+ outb(0x23, CONFIG_PORT);
+
+ /* Select logical device 3 */
+ outb(0x07, INDEX_PORT);
+ outb(0x03, DATA_PORT);
+
+ /* Set parallel port to DMA channel 3, ECP+EPP1.9,
+ enable EPP timeout */
+ outb(0x74, INDEX_PORT);
+ outb(0x03, DATA_PORT);
+
+ outb(0xf0, INDEX_PORT);
+ outb(0x0f, DATA_PORT);
+
+ outb(0xf1, INDEX_PORT);
+ outb(0x07, DATA_PORT);
+
+ /* Select logical device 4 */
+ outb(0x07, INDEX_PORT);
+ outb(0x04, DATA_PORT);
+
+ /* UART1 high speed mode */
+ outb(0xf0, INDEX_PORT);
+ outb(0x02, DATA_PORT);
+
+ /* Select logical device 5 */
+ outb(0x07, INDEX_PORT);
+ outb(0x05, DATA_PORT);
+
+ /* UART2 high speed mode */
+ outb(0xf0, INDEX_PORT);
+ outb(0x02, DATA_PORT);
+
+ /* Set Aladdin to RUN mode */
+ outb(0xbb, CONFIG_PORT);
+ }
+
return 0;
}
-__initcall(hw_init);
+__initcall(cats_hw_init);
+#endif
+
diff --git a/arch/arm/kernel/hw-sa1100.c b/arch/arm/kernel/hw-sa1100.c
index 539bb721b..862c3a2c4 100644
--- a/arch/arm/kernel/hw-sa1100.c
+++ b/arch/arm/kernel/hw-sa1100.c
@@ -10,9 +10,9 @@
*
*/
#include <linux/config.h>
+#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
-#include <linux/module.h>
#include <linux/sched.h>
#include <asm/delay.h>
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 7a761b7c6..40a47c45f 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -17,7 +17,6 @@
*/
#include <linux/config.h>
#include <linux/ptrace.h>
-#include <linux/errno.h>
#include <linux/kernel_stat.h>
#include <linux/signal.h>
#include <linux/sched.h>
@@ -26,7 +25,6 @@
#include <linux/malloc.h>
#include <linux/random.h>
#include <linux/smp.h>
-#include <linux/smp_lock.h>
#include <linux/init.h>
#include <asm/hardware.h>
diff --git a/arch/arm/kernel/isa.c b/arch/arm/kernel/isa.c
index a5424f8b6..17696acb0 100644
--- a/arch/arm/kernel/isa.c
+++ b/arch/arm/kernel/isa.c
@@ -13,7 +13,6 @@
#include <linux/stddef.h>
#include <linux/types.h>
-#include <linux/linkage.h>
#include <linux/fs.h>
#include <linux/sysctl.h>
#include <linux/init.h>
diff --git a/arch/arm/kernel/leds-footbridge.c b/arch/arm/kernel/leds-footbridge.c
index 4fa2237eb..b309c2ea3 100644
--- a/arch/arm/kernel/leds-footbridge.c
+++ b/arch/arm/kernel/leds-footbridge.c
@@ -18,8 +18,8 @@
* 02-05-1999 RMK Various cleanups
*/
#include <linux/config.h>
-#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/spinlock.h>
diff --git a/arch/arm/kernel/leds-sa1100.c b/arch/arm/kernel/leds-sa1100.c
index ef6918d7c..f2f0325c3 100644
--- a/arch/arm/kernel/leds-sa1100.c
+++ b/arch/arm/kernel/leds-sa1100.c
@@ -29,8 +29,8 @@
*
*/
#include <linux/config.h>
-#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/spinlock.h>
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 40b3b9e72..cab969c5c 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -7,28 +7,22 @@
#include <stdarg.h>
-#include <linux/errno.h>
+#include <linux/config.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
#include <linux/stddef.h>
#include <linux/unistd.h>
#include <linux/ptrace.h>
#include <linux/malloc.h>
-#include <linux/vmalloc.h>
#include <linux/user.h>
-#include <linux/a.out.h>
-#include <linux/interrupt.h>
-#include <linux/config.h>
#include <linux/delay.h>
#include <linux/reboot.h>
#include <linux/init.h>
-#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/io.h>
+#include <asm/uaccess.h>
/*
* Values for cpu_do_idle()
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 1684c5f5f..e45e03fcb 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -8,7 +8,6 @@
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
-#include <linux/errno.h>
#include <linux/ptrace.h>
#include <linux/user.h>
@@ -16,6 +15,10 @@
#include <asm/pgtable.h>
#include <asm/system.h>
+#include "ptrace.h"
+
+#define REG_PC 15
+#define REG_PSR 16
/*
* does not yet catch signals sent when the child dies.
* in exit.c or in signal.c.
@@ -27,6 +30,18 @@
#define BREAKINST 0xef9f0001
/*
+ * Get the address of the live pt_regs for the specified task.
+ * These are saved onto the top kernel stack when the process
+ * is not running.
+ */
+static inline struct pt_regs *
+get_user_regs(struct task_struct *task)
+{
+ return (struct pt_regs *)
+ ((unsigned long)task + 8192 - sizeof(struct pt_regs));
+}
+
+/*
* this routine will get a word off of the processes privileged stack.
* the offset is how far from the base addr as stored in the THREAD.
* this routine assumes that all the privileged stacks are in our
@@ -34,11 +49,7 @@
*/
static inline long get_stack_long(struct task_struct *task, int offset)
{
- struct pt_regs *regs;
-
- regs = (struct pt_regs *)((unsigned long)task + 8192 - sizeof(struct pt_regs));
-
- return regs->uregs[offset];
+ return get_user_regs(task)->uregs[offset];
}
/*
@@ -47,20 +58,16 @@ static inline long get_stack_long(struct task_struct *task, int offset)
* this routine assumes that all the privileged stacks are in our
* data space.
*/
-static inline long put_stack_long(struct task_struct *task, int offset,
- unsigned long data)
+static inline int
+put_stack_long(struct task_struct *task, int offset, long data)
{
- struct pt_regs *regs;
-
- regs = (struct pt_regs *)((unsigned long)task + 8192 - sizeof(struct pt_regs));
-
- regs->uregs[offset] = data;
+ get_user_regs(task)->uregs[offset] = data;
return 0;
}
-static int
-read_long(struct task_struct *child, unsigned long addr, unsigned long *res)
+static inline int
+read_tsk_long(struct task_struct *child, unsigned long addr, unsigned long *res)
{
int copied;
@@ -69,8 +76,8 @@ read_long(struct task_struct *child, unsigned long addr, unsigned long *res)
return copied != sizeof(*res) ? -EIO : 0;
}
-static int
-write_long(struct task_struct *child, unsigned long addr, unsigned long val)
+static inline int
+write_tsk_long(struct task_struct *child, unsigned long addr, unsigned long val)
{
int copied;
@@ -82,35 +89,33 @@ write_long(struct task_struct *child, unsigned long addr, unsigned long val)
/*
* Get value of register `rn' (in the instruction)
*/
-static unsigned long ptrace_getrn (struct task_struct *child, unsigned long insn)
+static unsigned long
+ptrace_getrn(struct task_struct *child, unsigned long insn)
{
unsigned int reg = (insn >> 16) & 15;
unsigned long val;
+ val = get_stack_long(child, reg);
if (reg == 15)
- val = pc_pointer (get_stack_long (child, reg));
- else
- val = get_stack_long (child, reg);
+ val = pc_pointer(val);
-printk ("r%02d=%08lX ", reg, val);
return val;
}
/*
* Get value of operand 2 (in an ALU instruction)
*/
-static unsigned long ptrace_getaluop2 (struct task_struct *child, unsigned long insn)
+static unsigned long
+ptrace_getaluop2(struct task_struct *child, unsigned long insn)
{
unsigned long val;
int shift;
int type;
-printk ("op2=");
if (insn & 1 << 25) {
val = insn & 255;
shift = (insn >> 8) & 15;
type = 3;
-printk ("(imm)");
} else {
val = get_stack_long (child, insn & 15);
@@ -120,9 +125,8 @@ printk ("(imm)");
shift = (insn >> 7) & 31;
type = (insn >> 5) & 3;
-printk ("(r%02ld)", insn & 15);
}
-printk ("sh%dx%d", type, shift);
+
switch (type) {
case 0: val <<= shift; break;
case 1: val >>= shift; break;
@@ -133,24 +137,23 @@ printk ("sh%dx%d", type, shift);
val = (val >> shift) | (val << (32 - shift));
break;
}
-printk ("=%08lX ", val);
return val;
}
/*
* Get value of operand 2 (in a LDR instruction)
*/
-static unsigned long ptrace_getldrop2 (struct task_struct *child, unsigned long insn)
+static unsigned long
+ptrace_getldrop2(struct task_struct *child, unsigned long insn)
{
unsigned long val;
int shift;
int type;
- val = get_stack_long (child, insn & 15);
+ val = get_stack_long(child, insn & 15);
shift = (insn >> 7) & 31;
type = (insn >> 5) & 3;
-printk ("op2=r%02ldsh%dx%d", insn & 15, shift, type);
switch (type) {
case 0: val <<= shift; break;
case 1: val >>= shift; break;
@@ -161,7 +164,6 @@ printk ("op2=r%02ldsh%dx%d", insn & 15, shift, type);
val = (val >> shift) | (val << (32 - shift));
break;
}
-printk ("=%08lX ", val);
return val;
}
@@ -170,95 +172,72 @@ get_branch_address(struct task_struct *child, unsigned long pc, unsigned long in
{
unsigned long alt = 0;
-printk(KERN_DEBUG "ptrace_set_bpt: insn=%08lX pc=%08lX ", insn, pc);
- switch (insn & 0x0e100000) {
+ switch (insn & 0x0e000000) {
case 0x00000000:
- case 0x00100000:
- case 0x02000000:
- case 0x02100000: /* data processing */
- printk ("data ");
- switch (insn & 0x01e0f000) {
- case 0x0000f000:
- alt = ptrace_getrn(child, insn) & ptrace_getaluop2(child, insn);
- break;
- case 0x0020f000:
- alt = ptrace_getrn(child, insn) ^ ptrace_getaluop2(child, insn);
- break;
- case 0x0040f000:
- alt = ptrace_getrn(child, insn) - ptrace_getaluop2(child, insn);
- break;
- case 0x0060f000:
- alt = ptrace_getaluop2(child, insn) - ptrace_getrn(child, insn);
- break;
- case 0x0080f000:
- alt = ptrace_getrn(child, insn) + ptrace_getaluop2(child, insn);
- break;
- case 0x00a0f000:
- alt = ptrace_getrn(child, insn) + ptrace_getaluop2(child, insn) +
- (get_stack_long (child, 16/*REG_PSR*/) & CC_C_BIT ? 1 : 0);
- break;
- case 0x00c0f000:
- alt = ptrace_getrn(child, insn) - ptrace_getaluop2(child, insn) +
- (get_stack_long (child, 16/*REG_PSR*/) & CC_C_BIT ? 1 : 0);
- break;
- case 0x00e0f000:
- alt = ptrace_getaluop2(child, insn) - ptrace_getrn(child, insn) +
- (get_stack_long (child, 16/*REG_PSR*/) & CC_C_BIT ? 1 : 0);
- break;
- case 0x0180f000:
- alt = ptrace_getrn(child, insn) | ptrace_getaluop2(child, insn);
- break;
- case 0x01a0f000:
- alt = ptrace_getaluop2(child, insn);
- break;
- case 0x01c0f000:
- alt = ptrace_getrn(child, insn) & ~ptrace_getaluop2(child, insn);
- break;
- case 0x01e0f000:
- alt = ~ptrace_getaluop2(child, insn);
+ case 0x02000000: {
+ /*
+ * data processing
+ */
+ long aluop1, aluop2, ccbit;
+
+ if ((insn & 0xf000) != 0xf000)
break;
+
+ aluop1 = ptrace_getrn(child, insn);
+ aluop2 = ptrace_getaluop2(child, insn);
+ ccbit = get_stack_long(child, REG_PSR) & CC_C_BIT ? 1 : 0;
+
+ switch (insn & 0x01e00000) {
+ case 0x00000000: alt = aluop1 & aluop2; break;
+ case 0x00200000: alt = aluop1 ^ aluop2; break;
+ case 0x00400000: alt = aluop1 - aluop2; break;
+ case 0x00600000: alt = aluop2 - aluop1; break;
+ case 0x00800000: alt = aluop1 + aluop2; break;
+ case 0x00a00000: alt = aluop1 + aluop2 + ccbit; break;
+ case 0x00c00000: alt = aluop1 - aluop2 + ccbit; break;
+ case 0x00e00000: alt = aluop2 - aluop1 + ccbit; break;
+ case 0x01800000: alt = aluop1 | aluop2; break;
+ case 0x01a00000: alt = aluop2; break;
+ case 0x01c00000: alt = aluop1 & ~aluop2; break;
+ case 0x01e00000: alt = ~aluop2; break;
}
break;
+ }
+
+ case 0x04000000:
+ case 0x06000000:
+ /*
+ * ldr
+ */
+ if ((insn & 0x0010f000) == 0x0010f000) {
+ unsigned long base;
- case 0x04100000: /* ldr */
- if ((insn & 0xf000) == 0xf000) {
-printk ("ldr ");
- alt = ptrace_getrn(child, insn);
+ base = ptrace_getrn(child, insn);
if (insn & 1 << 24) {
- if (insn & 1 << 23)
- alt += ptrace_getldrop2 (child, insn);
+ long aluop2;
+
+ if (insn & 0x02000000)
+ aluop2 = ptrace_getldrop2(child, insn);
else
- alt -= ptrace_getldrop2 (child, insn);
- }
- if (read_long (child, alt, &alt) < 0)
- alt = 0; /* not valid */
- else
- alt = pc_pointer (alt);
- }
- break;
+ aluop2 = insn & 0xfff;
- case 0x06100000: /* ldr imm */
- if ((insn & 0xf000) == 0xf000) {
-printk ("ldrimm ");
- alt = ptrace_getrn(child, insn);
- if (insn & 1 << 24) {
if (insn & 1 << 23)
- alt += insn & 0xfff;
+ base += aluop2;
else
- alt -= insn & 0xfff;
+ base -= aluop2;
}
- if (read_long (child, alt, &alt) < 0)
- alt = 0; /* not valid */
- else
- alt = pc_pointer (alt);
+ if (read_tsk_long(child, base, &alt) == 0)
+ alt = pc_pointer(alt);
}
break;
- case 0x08100000: /* ldm */
- if (insn & (1 << 15)) {
+ case 0x08000000:
+ /*
+ * ldm
+ */
+ if ((insn & 0x00108000) == 0x00108000) {
unsigned long base;
- int nr_regs;
-printk ("ldm ");
+ unsigned int nr_regs;
if (insn & (1 << 23)) {
nr_regs = insn & 65535;
@@ -278,23 +257,22 @@ printk ("ldm ");
nr_regs = 0;
}
- base = ptrace_getrn (child, insn);
+ base = ptrace_getrn(child, insn);
- if (read_long (child, base + nr_regs, &alt) < 0)
- alt = 0; /* not valid */
- else
+ if (read_tsk_long(child, base + nr_regs, &alt) == 0)
alt = pc_pointer (alt);
break;
}
break;
- case 0x0a000000:
- case 0x0a100000: { /* bl or b */
+ case 0x0a000000: {
+ /*
+ * bl or b
+ */
signed long displ;
-printk ("b/bl ");
/* It's a branch/branch link: instead of trying to
* figure out whether the branch will be taken or not,
- * we'll put a breakpoint at either location. This is
+ * we'll put a breakpoint at both locations. This is
* simpler, more reliable, and probably not a whole lot
* slower than the alternative approach of emulating the
* branch.
@@ -306,7 +284,6 @@ printk ("b/bl ");
}
break;
}
-printk ("=%08lX\n", alt);
return alt;
}
@@ -318,9 +295,9 @@ add_breakpoint(struct task_struct *child, struct debug_info *dbg, unsigned long
int res = -EINVAL;
if (nr < 2) {
- res = read_long(child, addr, &dbg->bp[nr].insn);
+ res = read_tsk_long(child, addr, &dbg->bp[nr].insn);
if (res == 0)
- res = write_long(child, addr, BREAKINST);
+ res = write_tsk_long(child, addr, BREAKINST);
if (res == 0) {
dbg->bp[nr].address = addr;
@@ -332,257 +309,309 @@ add_breakpoint(struct task_struct *child, struct debug_info *dbg, unsigned long
return res;
}
-int ptrace_set_bpt (struct task_struct *child)
+int ptrace_set_bpt(struct task_struct *child)
{
- struct debug_info *dbg = &child->thread.debug;
- unsigned long insn, pc, alt;
+ unsigned long insn, pc;
int res;
- pc = pc_pointer (get_stack_long (child, 15/*REG_PC*/));
+ pc = pc_pointer(get_stack_long(child, REG_PC));
- res = read_long(child, pc, &insn);
- if (res >= 0) {
- res = 0;
+ res = read_tsk_long(child, pc, &insn);
+ if (!res) {
+ struct debug_info *dbg = &child->thread.debug;
+ unsigned long alt;
dbg->nsaved = 0;
- res = add_breakpoint(child, dbg, pc + 4);
+ alt = get_branch_address(child, pc, insn);
+ if (alt)
+ res = add_breakpoint(child, dbg, alt);
- if (res == 0) {
- alt = get_branch_address(child, pc, insn);
- if (alt)
- res = add_breakpoint(child, dbg, alt);
- }
+ if (!res && (!alt || predicate(insn) != PREDICATE_ALWAYS))
+ res = add_breakpoint(child, dbg, pc + 4);
}
return res;
}
-/* Ensure no single-step breakpoint is pending. Returns non-zero
+/*
+ * Ensure no single-step breakpoint is pending. Returns non-zero
* value if child was being single-stepped.
*/
-int ptrace_cancel_bpt (struct task_struct *child)
+void __ptrace_cancel_bpt(struct task_struct *child)
{
struct debug_info *dbg = &child->thread.debug;
- unsigned long tmp;
int i, nsaved = dbg->nsaved;
dbg->nsaved = 0;
if (nsaved > 2) {
- printk ("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved);
+ printk("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved);
nsaved = 2;
}
for (i = 0; i < nsaved; i++) {
- read_long(child, dbg->bp[i].address, &tmp);
+ unsigned long tmp;
+
+ read_tsk_long(child, dbg->bp[i].address, &tmp);
if (tmp != BREAKINST)
printk(KERN_ERR "ptrace_cancel_bpt: weirdness\n");
- write_long(child, dbg->bp[i].address, dbg->bp[i].insn);
+ write_tsk_long(child, dbg->bp[i].address, dbg->bp[i].insn);
}
-
- return nsaved != 0;
}
-asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
+static int do_ptrace(int request, struct task_struct *child, long addr, long data)
{
- struct task_struct *child;
+ unsigned long tmp;
int ret;
- lock_kernel();
- ret = -EPERM;
- if (request == PTRACE_TRACEME) {
- /* are we already being traced? */
- if (current->ptrace & PT_PTRACED)
- goto out;
- /* set the ptrace bit in the process flags. */
- current->ptrace |= PT_PTRACED;
- ret = 0;
- goto out;
- }
- if (pid == 1) /* you may not mess with init */
- goto out;
- ret = -ESRCH;
- if (!(child = find_task_by_pid(pid)))
- goto out;
- ret = -EPERM;
- if (request == PTRACE_ATTACH) {
- if (child == current)
- goto out;
- if ((!child->dumpable ||
- (current->uid != child->euid) ||
- (current->uid != child->suid) ||
- (current->uid != child->uid) ||
- (current->gid != child->egid) ||
- (current->gid != child->sgid) ||
- (!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
- (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
- goto out;
- /* the same process cannot be attached many times */
- if (child->ptrace & PT_PTRACED)
- goto out;
- child->ptrace |= PT_PTRACED;
- if (child->p_pptr != current) {
- REMOVE_LINKS(child);
- child->p_pptr = current;
- SET_LINKS(child);
- }
- send_sig(SIGSTOP, child, 1);
- ret = 0;
- goto out;
- }
- ret = -ESRCH;
- if (!(child->ptrace & PT_PTRACED))
- goto out;
- if (child->state != TASK_STOPPED) {
- if (request != PTRACE_KILL)
- goto out;
- }
- if (child->p_pptr != current)
- goto out;
-
switch (request) {
- case PTRACE_PEEKTEXT: /* read word at location addr. */
- case PTRACE_PEEKDATA: {
- unsigned long tmp;
-
- ret = read_long(child, addr, &tmp);
+ /*
+ * read word at location "addr" in the child process.
+ */
+ case PTRACE_PEEKTEXT:
+ case PTRACE_PEEKDATA:
+ ret = read_tsk_long(child, addr, &tmp);
if (!ret)
ret = put_user(tmp, (unsigned long *) data);
- goto out;
- }
-
- case PTRACE_PEEKUSR: { /* read the word at location addr in the USER area. */
- unsigned long tmp;
+ break;
+ /*
+ * read the word at location "addr" in the user registers.
+ */
+ case PTRACE_PEEKUSR:
ret = -EIO;
if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
- goto out;
+ break;
tmp = 0; /* Default return condition */
- if (addr < sizeof (struct pt_regs))
+ if (addr < sizeof(struct pt_regs))
tmp = get_stack_long(child, (int)addr >> 2);
ret = put_user(tmp, (unsigned long *)data);
- goto out;
- }
+ break;
- case PTRACE_POKETEXT: /* write the word at location addr. */
+ /*
+ * write the word at location addr.
+ */
+ case PTRACE_POKETEXT:
case PTRACE_POKEDATA:
- ret = write_long(child, addr, data);
- goto out;
+ ret = write_tsk_long(child, addr, data);
+ break;
- case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
+ /*
+ * write the word at location addr in the user registers.
+ */
+ case PTRACE_POKEUSR:
ret = -EIO;
if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
- goto out;
+ break;
if (addr < sizeof (struct pt_regs))
ret = put_stack_long(child, (int)addr >> 2, data);
- goto out;
+ break;
- case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
- case PTRACE_CONT: /* restart after signal. */
+ /*
+ * continue/restart and stop at next (return from) syscall
+ */
+ case PTRACE_SYSCALL:
+ case PTRACE_CONT:
ret = -EIO;
if ((unsigned long) data > _NSIG)
- goto out;
+ break;
if (request == PTRACE_SYSCALL)
child->ptrace |= PT_TRACESYS;
else
child->ptrace &= ~PT_TRACESYS;
child->exit_code = data;
- wake_up_process (child);
/* make sure single-step breakpoint is gone. */
- ptrace_cancel_bpt (child);
+ __ptrace_cancel_bpt(child);
+ wake_up_process(child);
ret = 0;
- goto out;
+ break;
- /* make the child exit. Best I can do is send it a sigkill.
+ /*
+ * make the child exit. Best I can do is send it a sigkill.
* perhaps it should be put in the status that it wants to
* exit.
*/
case PTRACE_KILL:
- if (child->state == TASK_ZOMBIE) /* already dead */
- return 0;
- wake_up_process (child);
+ /* already dead */
+ ret = 0;
+ if (child->state == TASK_ZOMBIE)
+ break;
child->exit_code = SIGKILL;
/* make sure single-step breakpoint is gone. */
- ptrace_cancel_bpt (child);
+ __ptrace_cancel_bpt(child);
+ wake_up_process(child);
ret = 0;
- goto out;
+ break;
- case PTRACE_SINGLESTEP: /* execute single instruction. */
+ /*
+ * execute single instruction.
+ */
+ case PTRACE_SINGLESTEP:
ret = -EIO;
if ((unsigned long) data > _NSIG)
- goto out;
+ break;
child->thread.debug.nsaved = -1;
child->ptrace &= ~PT_TRACESYS;
- wake_up_process(child);
child->exit_code = data;
/* give it a chance to run. */
+ wake_up_process(child);
ret = 0;
- goto out;
-
- case PTRACE_GETREGS:
- { /* Get all gp regs from the child. */
- unsigned char *stack;
+ break;
+
+ /*
+ * detach a process that was attached.
+ */
+ case PTRACE_DETACH:
+ ret = -EIO;
+ if ((unsigned long) data > _NSIG)
+ break;
+ child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
+ child->exit_code = data;
+ write_lock_irq(&tasklist_lock);
+ REMOVE_LINKS(child);
+ child->p_pptr = child->p_opptr;
+ SET_LINKS(child);
+ write_unlock_irq(&tasklist_lock);
+ /* make sure single-step breakpoint is gone. */
+ __ptrace_cancel_bpt(child);
+ wake_up_process (child);
+ ret = 0;
+ break;
+
+ /*
+ * Get all gp regs from the child.
+ */
+ case PTRACE_GETREGS: {
+ struct pt_regs *regs = get_user_regs(child);
ret = 0;
- stack = (unsigned char *)((unsigned long)child + 8192 - sizeof(struct pt_regs));
- if (copy_to_user((void *)data, stack,
+ if (copy_to_user((void *)data, regs,
sizeof(struct pt_regs)))
ret = -EFAULT;
- goto out;
- };
+ break;
+ }
- case PTRACE_SETREGS:
- {
- /* Set all gp regs in the child. */
- unsigned char *stack;
+ /*
+ * Set all gp regs in the child.
+ */
+ case PTRACE_SETREGS: {
+ struct pt_regs *regs = get_user_regs(child);
ret = 0;
- stack = (unsigned char *)((unsigned long)child + 8192 - sizeof(struct pt_regs));
- if (copy_from_user(stack, (void *)data,
+ if (copy_from_user(regs, (void *)data,
sizeof(struct pt_regs)))
ret = -EFAULT;
- goto out;
- };
+ break;
+ }
- case PTRACE_GETFPREGS:
- /* Get the child FPU state. */
- ret = 0;
- if (copy_to_user((void *)data, &child->thread.fpstate,
- sizeof(struct user_fp)))
- ret = -EFAULT;
- goto out;
+ /*
+ * Get the child FPU state.
+ */
+ case PTRACE_GETFPREGS:
+ ret = -EIO;
+ if (!access_ok(VERIFY_WRITE, (void *)data, sizeof(struct user_fp)))
+ break;
+
+ /* we should check child->used_math here */
+ ret = __copy_to_user((void *)data, &child->thread.fpstate,
+ sizeof(struct user_fp)) ? -EFAULT : 0;
+ break;
+ /*
+ * Set the child FPU state.
+ */
case PTRACE_SETFPREGS:
- /* Set the child FPU state. */
- ret = 0;
- if (copy_from_user(&child->thread.fpstate, (void *)data,
- sizeof(struct user_fp)))
- ret = -EFAULT;
- goto out;
-
- case PTRACE_DETACH: /* detach a process that was attached. */
ret = -EIO;
- if ((unsigned long) data > _NSIG)
- goto out;
- child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
- wake_up_process (child);
- child->exit_code = data;
- REMOVE_LINKS(child);
- child->p_pptr = child->p_opptr;
- SET_LINKS(child);
- /* make sure single-step breakpoint is gone. */
- ptrace_cancel_bpt (child);
- ret = 0;
- goto out;
+ if (!access_ok(VERIFY_READ, (void *)data, sizeof(struct user_fp)))
+ break;
+
+ child->used_math = 1;
+ ret = __copy_from_user(&child->thread.fpstate, (void *)data,
+ sizeof(struct user_fp)) ? -EFAULT : 0;
+ break;
default:
ret = -EIO;
+ break;
+ }
+
+ return ret;
+}
+
+asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
+{
+ struct task_struct *child;
+ int ret;
+
+ lock_kernel();
+ ret = -EPERM;
+ if (request == PTRACE_TRACEME) {
+ /* are we already being traced? */
+ if (current->ptrace & PT_PTRACED)
goto out;
+ /* set the ptrace bit in the process flags. */
+ current->ptrace |= PT_PTRACED;
+ ret = 0;
+ goto out;
}
+ ret = -ESRCH;
+ read_lock(&tasklist_lock);
+ child = find_task_by_pid(pid);
+ if (child)
+ get_task_struct(child);
+ read_unlock(&tasklist_lock);
+ if (!child)
+ goto out;
+
+ ret = -EPERM;
+ if (pid == 1) /* you may not mess with init */
+ goto out_tsk;
+
+ if (request == PTRACE_ATTACH) {
+ if (child == current)
+ goto out_tsk;
+ if ((!child->dumpable ||
+ (current->uid != child->euid) ||
+ (current->uid != child->suid) ||
+ (current->uid != child->uid) ||
+ (current->gid != child->egid) ||
+ (current->gid != child->sgid) ||
+ (!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
+ (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
+ goto out_tsk;
+ /* the same process cannot be attached many times */
+ if (child->ptrace & PT_PTRACED)
+ goto out_tsk;
+ child->ptrace |= PT_PTRACED;
+
+ write_lock_irq(&tasklist_lock);
+ if (child->p_pptr != current) {
+ REMOVE_LINKS(child);
+ child->p_pptr = current;
+ SET_LINKS(child);
+ }
+ write_unlock_irq(&tasklist_lock);
+
+ send_sig(SIGSTOP, child, 1);
+ ret = 0;
+ goto out_tsk;
+ }
+ ret = -ESRCH;
+ if (!(child->ptrace & PT_PTRACED))
+ goto out_tsk;
+ if (child->state != TASK_STOPPED && request != PTRACE_KILL)
+ goto out_tsk;
+ if (child->p_pptr != current)
+ goto out_tsk;
+
+ ret = do_ptrace(request, child, addr, data);
+
+out_tsk:
+ free_task_struct(child);
out:
unlock_kernel();
return ret;
diff --git a/arch/arm/kernel/ptrace.h b/arch/arm/kernel/ptrace.h
new file mode 100644
index 000000000..feae0acd8
--- /dev/null
+++ b/arch/arm/kernel/ptrace.h
@@ -0,0 +1,16 @@
+extern void __ptrace_cancel_bpt(struct task_struct *);
+extern int ptrace_set_bpt(struct task_struct *);
+
+/*
+ * Clear a breakpoint, if one exists.
+ */
+static inline int ptrace_cancel_bpt(struct task_struct *tsk)
+{
+ int nsaved = tsk->thread.debug.nsaved;
+
+ if (nsaved)
+ __ptrace_cancel_bpt(tsk);
+
+ return nsaved;
+}
+
diff --git a/arch/arm/kernel/semaphore.c b/arch/arm/kernel/semaphore.c
index 93a370f2d..8118b6a68 100644
--- a/arch/arm/kernel/semaphore.c
+++ b/arch/arm/kernel/semaphore.c
@@ -8,7 +8,6 @@
* Modified for ARM by Russell King
*/
#include <linux/sched.h>
-#include <linux/errno.h>
#include <asm/semaphore.h>
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 1f4295540..c6010476a 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -35,6 +35,7 @@ extern void paging_init(struct meminfo *);
extern void bootmem_init(struct meminfo *);
extern void reboot_setup(char *str);
extern void disable_hlt(void);
+extern unsigned long memparse(char *ptr, char **retptr);
extern int root_mountflags;
extern int _stext, _text, _etext, _edata, _end;
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 431dd96c1..3e6cf6cb4 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -10,18 +10,19 @@
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/kernel.h>
-#include <linux/signal.h>
#include <linux/errno.h>
+#include <linux/signal.h>
#include <linux/wait.h>
#include <linux/ptrace.h>
-#include <linux/unistd.h>
#include <linux/stddef.h>
-#include <linux/binfmts.h>
+#include <linux/unistd.h>
#include <linux/tty.h>
+#include <asm/pgalloc.h>
#include <asm/ucontext.h>
#include <asm/uaccess.h>
-#include <asm/pgalloc.h>
+
+#include "ptrace.h"
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
@@ -31,8 +32,6 @@
asmlinkage int sys_wait4(pid_t pid, unsigned long * stat_addr,
int options, unsigned long *ru);
asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall);
-extern int ptrace_cancel_bpt (struct task_struct *);
-extern int ptrace_set_bpt (struct task_struct *);
int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
{
@@ -234,7 +233,7 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
goto badframe;
/* Send SIGTRAP if we're single-stepping */
- if (ptrace_cancel_bpt (current))
+ if (ptrace_cancel_bpt(current))
send_sig(SIGTRAP, current, 1);
return regs->ARM_r0;
@@ -274,7 +273,7 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
goto badframe;
/* Send SIGTRAP if we're single-stepping */
- if (ptrace_cancel_bpt (current))
+ if (ptrace_cancel_bpt(current))
send_sig(SIGTRAP, current, 1);
return regs->ARM_r0;
@@ -500,7 +499,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
if (!oldset)
oldset = &current->blocked;
- single_stepping = ptrace_cancel_bpt (current);
+ single_stepping = ptrace_cancel_bpt(current);
for (;;) {
unsigned long signr;
@@ -518,7 +517,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD);
schedule();
- single_stepping |= ptrace_cancel_bpt (current);
+ single_stepping |= ptrace_cancel_bpt(current);
/* We're back. Did the debugger cancel the sig? */
if (!(signr = current->exit_code))
@@ -617,7 +616,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
/* Whee! Actually deliver the signal. */
handle_signal(signr, ka, &info, oldset, regs);
if (single_stepping)
- ptrace_set_bpt (current);
+ ptrace_set_bpt(current);
return 1;
}
@@ -629,6 +628,6 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
regs->ARM_pc -= 4;
}
if (single_stepping)
- ptrace_set_bpt (current);
+ ptrace_set_bpt(current);
return 0;
}
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index bdb725551..d7f6640eb 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -13,7 +13,6 @@
* "A Kernel Model for Precision Timekeeping" by Dave Mills
*/
#include <linux/config.h>
-#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 1d692dd35..188f89722 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -17,16 +17,18 @@
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/spinlock.h>
+#include <linux/ptrace.h>
#include <linux/init.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
#include <asm/atomic.h>
+#include <asm/io.h>
#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#include "ptrace.h"
extern void c_backtrace (unsigned long fp, int pmode);
-extern int ptrace_cancel_bpt (struct task_struct *);
char *processor_modes[]=
{ "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" ,
@@ -46,8 +48,6 @@ static inline void console_verbose(void)
console_loglevel = 15;
}
-int kstack_depth_to_print = 200;
-
/*
* Stack pointers should always be within the kernels view of
* physical memory. If it is not there, then we can't dump
@@ -199,37 +199,48 @@ void die_if_kernel(const char *str, struct pt_regs *regs, int err)
die(str, regs, err);
}
-void bad_user_access_alignment(const void *ptr)
-{
- printk(KERN_ERR "bad user access alignment: ptr = %p, pc = %p\n", ptr,
- __builtin_return_address(0));
- current->thread.error_code = 0;
- current->thread.trap_no = 11;
- force_sig(SIGBUS, current);
-/* die_if_kernel("Oops - bad user access alignment", regs, mode);*/
-}
-
asmlinkage void do_undefinstr(int address, struct pt_regs *regs, int mode)
{
+ unsigned long addr = instruction_pointer(regs);
+ siginfo_t info;
+
#ifdef CONFIG_DEBUG_USER
printk(KERN_INFO "%s (%d): undefined instruction: pc=%08lx\n",
- current->comm, current->pid, instruction_pointer(regs));
+ current->comm, current->pid, addr);
#endif
+
current->thread.error_code = 0;
current->thread.trap_no = 6;
- force_sig(SIGILL, current);
+
+ info.si_signo = SIGILL;
+ info.si_errno = 0;
+ info.si_code = ILL_ILLOPC;
+ info.si_addr = (void *)addr;
+
+ force_sig_info(SIGILL, &info, current);
+
die_if_kernel("Oops - undefined instruction", regs, mode);
}
asmlinkage void do_excpt(int address, struct pt_regs *regs, int mode)
{
+ siginfo_t info;
+
#ifdef CONFIG_DEBUG_USER
printk(KERN_INFO "%s (%d): address exception: pc=%08lx\n",
current->comm, current->pid, instruction_pointer(regs));
#endif
+
current->thread.error_code = 0;
current->thread.trap_no = 11;
- force_sig(SIGBUS, current);
+
+ info.si_signo = SIGBUS;
+ info.si_errno = 0;
+ info.si_code = BUS_ADRERR;
+ info.si_addr = (void *)address;
+
+ force_sig_info(SIGBUS, &info, current);
+
die_if_kernel("Oops - address exception", regs, mode);
}
@@ -269,32 +280,38 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason, int proc_mode)
}
/*
- * 'math_state_restore()' saves the current math information in the
- * old math state array, and gets the new ones from the current task.
- *
- * We no longer save/restore the math state on every context switch
- * any more. We only do this now if it actually gets used.
- */
-asmlinkage void math_state_restore (void)
-{
- current->used_math = 1;
-}
-
-/*
* Handle some more esoteric system calls
*/
-asmlinkage int arm_syscall (int no, struct pt_regs *regs)
+asmlinkage int arm_syscall(int no, struct pt_regs *regs)
{
+ siginfo_t info;
+
switch (no) {
case 0: /* branch through 0 */
- force_sig(SIGSEGV, current);
+ info.si_signo = SIGSEGV;
+ info.si_errno = 0;
+ info.si_code = SEGV_MAPERR;
+ info.si_addr = NULL;
+
+ force_sig_info(SIGSEGV, &info, current);
+
die_if_kernel("branch through zero", regs, 0);
break;
- case 1: /* SWI_BREAK_POINT */
- regs->ARM_pc -= 4; /* Decrement PC by one instruction */
- ptrace_cancel_bpt(current);
- force_sig(SIGTRAP, current);
+ case 1: /* SWI BREAK_POINT */
+ /*
+ * The PC is always left pointing at the next
+ * instruction. Fix this.
+ */
+ regs->ARM_pc -= 4;
+ __ptrace_cancel_bpt(current);
+
+ info.si_signo = SIGTRAP;
+ info.si_errno = 0;
+ info.si_code = TRAP_BRKPT;
+ info.si_addr = (void *)instruction_pointer(regs);
+
+ force_sig_info(SIGTRAP, &info, current);
return regs->ARM_r0;
case 2: /* sys_cacheflush */
@@ -350,29 +367,24 @@ asmlinkage void deferred(int n, struct pt_regs *regs)
die_if_kernel("Oops", regs, n);
}
-asmlinkage void arm_malalignedptr(const char *str, void *pc, volatile void *ptr)
-{
- printk("Mal-aligned pointer in %s: %p (PC=%p)\n", str, ptr, pc);
-}
-
-asmlinkage void arm_invalidptr(const char *function, int size)
+void __bad_xchg(volatile void *ptr, int size)
{
- printk("Invalid pointer size in %s (pc=%p) size %d\n",
- function, __builtin_return_address(0), size);
+ printk("xchg: bad data size: pc 0x%p, ptr 0x%p, size %d\n",
+ __builtin_return_address(0), ptr, size);
+ BUG();
}
/*
- * A data abort trap was taken, but the instruction was not an instruction
- * which should cause the trap to be taken. Try to abort it. Note that
- * the while(1) is there because we cannot currently handle returning from
- * this function.
+ * A data abort trap was taken, but we did not handle the instruction.
+ * Try to abort the user program, or panic if it was the kernel.
*/
asmlinkage void
baddataabort(int code, unsigned long instr, struct pt_regs *regs)
{
unsigned long addr = instruction_pointer(regs);
+ siginfo_t info;
-#ifdef CONFIG_DEBUG_ERRORS
+#ifdef CONFIG_DEBUG_USER
dump_instr(addr, 1);
{
pgd_t *pgd;
@@ -389,16 +401,22 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs)
printk ("\n");
}
#endif
- force_sig(SIGILL, current);
+
+ info.si_signo = SIGILL;
+ info.si_errno = 0;
+ info.si_code = ILL_ILLOPC;
+ info.si_addr = (void *)addr;
+
+ force_sig_info(SIGILL, &info, current);
die_if_kernel("unknown data abort code", regs, instr);
- while (1);
}
void __bug(const char *file, int line, void *data)
{
- printk(KERN_CRIT"kernel BUG at %s:%d!\n", file, line);
+ printk(KERN_CRIT"kernel BUG at %s:%d!", file, line);
if (data)
- printk(KERN_CRIT"extra data = %p\n", data);
+ printk(KERN_CRIT" - extra data = %p", data);
+ printk("\n");
BUG();
}