aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/kernel
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-10-15 13:46:29 +0200
committerIngo Molnar <mingo@elte.hu>2008-10-15 13:46:29 +0200
commitb2aaf8f74cdc84a9182f6cabf198b7763bcb9d40 (patch)
tree53ccb1c2c14751fe69cf93102e76e97021f6df07 /arch/arm/kernel
parent4f962d4d65923d7b722192e729840cfb79af0a5a (diff)
parent278429cff8809958d25415ba0ed32b59866ab1a8 (diff)
Merge branch 'linus' into stackprotector
Conflicts: arch/x86/kernel/Makefile include/asm-x86/pda.h
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/.gitignore1
-rw-r--r--arch/arm/kernel/Makefile8
-rw-r--r--arch/arm/kernel/armksyms.c9
-rw-r--r--arch/arm/kernel/atags.c83
-rw-r--r--arch/arm/kernel/bios32.c2
-rw-r--r--arch/arm/kernel/calls.S10
-rw-r--r--arch/arm/kernel/crunch-bits.S2
-rw-r--r--arch/arm/kernel/crunch.c4
-rw-r--r--arch/arm/kernel/debug.S7
-rw-r--r--arch/arm/kernel/dma-isa.c3
-rw-r--r--arch/arm/kernel/dma.c17
-rw-r--r--arch/arm/kernel/ecard.c26
-rw-r--r--arch/arm/kernel/ecard.h13
-rw-r--r--arch/arm/kernel/elf.c79
-rw-r--r--arch/arm/kernel/entry-armv.S18
-rw-r--r--arch/arm/kernel/entry-common.S78
-rw-r--r--arch/arm/kernel/fiq.c1
-rw-r--r--arch/arm/kernel/ftrace.c116
-rw-r--r--arch/arm/kernel/head-common.S21
-rw-r--r--arch/arm/kernel/head-nommu.S5
-rw-r--r--arch/arm/kernel/head.S12
-rw-r--r--arch/arm/kernel/init_task.c2
-rw-r--r--arch/arm/kernel/io.c3
-rw-r--r--arch/arm/kernel/irq.c12
-rw-r--r--arch/arm/kernel/kgdb.c199
-rw-r--r--arch/arm/kernel/kprobes-decode.c4
-rw-r--r--arch/arm/kernel/kprobes.c13
-rw-r--r--arch/arm/kernel/machine_kexec.c4
-rw-r--r--arch/arm/kernel/module.c3
-rw-r--r--arch/arm/kernel/process.c41
-rw-r--r--arch/arm/kernel/ptrace.c10
-rw-r--r--arch/arm/kernel/setup.c268
-rw-r--r--arch/arm/kernel/signal.c2
-rw-r--r--arch/arm/kernel/smp.c168
-rw-r--r--arch/arm/kernel/stacktrace.c35
-rw-r--r--arch/arm/kernel/sys_arm.c3
-rw-r--r--arch/arm/kernel/sys_oabi-compat.c2
-rw-r--r--arch/arm/kernel/time.c126
-rw-r--r--arch/arm/kernel/traps.c52
-rw-r--r--arch/arm/kernel/xscale-cp0.c2
40 files changed, 778 insertions, 686 deletions
diff --git a/arch/arm/kernel/.gitignore b/arch/arm/kernel/.gitignore
new file mode 100644
index 00000000000..c5f676c3c22
--- /dev/null
+++ b/arch/arm/kernel/.gitignore
@@ -0,0 +1 @@
+vmlinux.lds
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index ad455ff5aeb..4305345987d 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -4,9 +4,13 @@
AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
+ifdef CONFIG_DYNAMIC_FTRACE
+CFLAGS_REMOVE_ftrace.o = -pg
+endif
+
# Object file lists.
-obj-y := compat.o entry-armv.o entry-common.o irq.o \
+obj-y := compat.o elf.o entry-armv.o entry-common.o irq.o \
process.o ptrace.o setup.o signal.o \
sys_arm.o stacktrace.o time.o traps.o
@@ -18,11 +22,13 @@ obj-$(CONFIG_ARTHUR) += arthur.o
obj-$(CONFIG_ISA_DMA) += dma-isa.o
obj-$(CONFIG_PCI) += bios32.o isa.o
obj-$(CONFIG_SMP) += smp.o
+obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
obj-$(CONFIG_KPROBES) += kprobes.o kprobes-decode.o
obj-$(CONFIG_ATAGS_PROC) += atags.o
obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o
obj-$(CONFIG_ARM_THUMBEE) += thumbee.o
+obj-$(CONFIG_KGDB) += kgdb.o
obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o
AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index 688b7b1ee41..2357b1cf1cf 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -13,11 +13,12 @@
#include <linux/delay.h>
#include <linux/in6.h>
#include <linux/syscalls.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
#include <asm/checksum.h>
-#include <asm/io.h>
#include <asm/system.h>
-#include <asm/uaccess.h>
+#include <asm/ftrace.h>
/*
* libgcc functions - functions that are used internally by the
@@ -181,3 +182,7 @@ EXPORT_SYMBOL(_find_next_bit_be);
#endif
EXPORT_SYMBOL(copy_page);
+
+#ifdef CONFIG_FTRACE
+EXPORT_SYMBOL(mcount);
+#endif
diff --git a/arch/arm/kernel/atags.c b/arch/arm/kernel/atags.c
index 64c420805e6..42a1a1415fa 100644
--- a/arch/arm/kernel/atags.c
+++ b/arch/arm/kernel/atags.c
@@ -1,5 +1,4 @@
#include <linux/slab.h>
-#include <linux/kexec.h>
#include <linux/proc_fs.h>
#include <asm/setup.h>
#include <asm/types.h>
@@ -7,9 +6,8 @@
struct buffer {
size_t size;
- char *data;
+ char data[];
};
-static struct buffer tags_buffer;
static int
read_buffer(char* page, char** start, off_t off, int count,
@@ -29,58 +27,57 @@ read_buffer(char* page, char** start, off_t off, int count,
return count;
}
-
-static int
-create_proc_entries(void)
-{
- struct proc_dir_entry* tags_entry;
-
- tags_entry = create_proc_read_entry("atags", 0400, NULL, read_buffer, &tags_buffer);
- if (!tags_entry)
- return -ENOMEM;
-
- return 0;
-}
-
-
-static char __initdata atags_copy_buf[KEXEC_BOOT_PARAMS_SIZE];
-static char __initdata *atags_copy;
+#define BOOT_PARAMS_SIZE 1536
+static char __initdata atags_copy[BOOT_PARAMS_SIZE];
void __init save_atags(const struct tag *tags)
{
- atags_copy = atags_copy_buf;
- memcpy(atags_copy, tags, KEXEC_BOOT_PARAMS_SIZE);
+ memcpy(atags_copy, tags, sizeof(atags_copy));
}
-
static int __init init_atags_procfs(void)
{
- struct tag *tag;
- int error;
+ /*
+ * This cannot go into save_atags() because kmalloc and proc don't work
+ * yet when it is called.
+ */
+ struct proc_dir_entry *tags_entry;
+ struct tag *tag = (struct tag *)atags_copy;
+ struct buffer *b;
+ size_t size;
- if (!atags_copy) {
- printk(KERN_WARNING "Exporting ATAGs: No saved tags found\n");
- return -EIO;
+ if (tag->hdr.tag != ATAG_CORE) {
+ printk(KERN_INFO "No ATAGs?");
+ return -EINVAL;
}
- for (tag = (struct tag *) atags_copy; tag->hdr.size; tag = tag_next(tag))
+ for (; tag->hdr.size; tag = tag_next(tag))
;
- tags_buffer.size = ((char *) tag - atags_copy) + sizeof(tag->hdr);
- tags_buffer.data = kmalloc(tags_buffer.size, GFP_KERNEL);
- if (tags_buffer.data == NULL)
- return -ENOMEM;
- memcpy(tags_buffer.data, atags_copy, tags_buffer.size);
-
- error = create_proc_entries();
- if (error) {
- printk(KERN_ERR "Exporting ATAGs: not enough memory\n");
- kfree(tags_buffer.data);
- tags_buffer.size = 0;
- tags_buffer.data = NULL;
- }
+ /* include the terminating ATAG_NONE */
+ size = (char *)tag - atags_copy + sizeof(struct tag_header);
- return error;
-}
+ WARN_ON(tag->hdr.tag != ATAG_NONE);
+
+ b = kmalloc(sizeof(*b) + size, GFP_KERNEL);
+ if (!b)
+ goto nomem;
+ b->size = size;
+ memcpy(b->data, atags_copy, size);
+
+ tags_entry = create_proc_read_entry("atags", 0400,
+ NULL, read_buffer, b);
+
+ if (!tags_entry)
+ goto nomem;
+
+ return 0;
+
+nomem:
+ kfree(b);
+ printk(KERN_ERR "Exporting ATAGs: not enough memory\n");
+
+ return -ENOMEM;
+}
arch_initcall(init_atags_procfs);
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index e5747547b44..17a59b6e521 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -10,8 +10,8 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/init.h>
+#include <linux/io.h>
-#include <asm/io.h>
#include <asm/mach-types.h>
#include <asm/mach/pci.h>
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index 30a67a5a40a..09a061cb783 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -262,10 +262,10 @@
/* 250 */ CALL(sys_epoll_create)
CALL(ABI(sys_epoll_ctl, sys_oabi_epoll_ctl))
CALL(ABI(sys_epoll_wait, sys_oabi_epoll_wait))
- CALL(sys_remap_file_pages)
+ CALL(sys_remap_file_pages)
CALL(sys_ni_syscall) /* sys_set_thread_area */
/* 255 */ CALL(sys_ni_syscall) /* sys_get_thread_area */
- CALL(sys_set_tid_address)
+ CALL(sys_set_tid_address)
CALL(sys_timer_create)
CALL(sys_timer_settime)
CALL(sys_timer_gettime)
@@ -364,6 +364,12 @@
CALL(sys_fallocate)
CALL(sys_timerfd_settime)
CALL(sys_timerfd_gettime)
+/* 355 */ CALL(sys_signalfd4)
+ CALL(sys_eventfd2)
+ CALL(sys_epoll_create1)
+ CALL(sys_dup3)
+ CALL(sys_pipe2)
+/* 360 */ CALL(sys_inotify_init1)
#ifndef syscalls_counted
.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
#define syscalls_counted
diff --git a/arch/arm/kernel/crunch-bits.S b/arch/arm/kernel/crunch-bits.S
index a26886758c6..0ec9bb48fab 100644
--- a/arch/arm/kernel/crunch-bits.S
+++ b/arch/arm/kernel/crunch-bits.S
@@ -16,7 +16,7 @@
#include <asm/ptrace.h>
#include <asm/thread_info.h>
#include <asm/asm-offsets.h>
-#include <asm/arch/ep93xx-regs.h>
+#include <mach/ep93xx-regs.h>
/*
* We can't use hex constants here due to a bug in gas.
diff --git a/arch/arm/kernel/crunch.c b/arch/arm/kernel/crunch.c
index 627d79414c9..99995c2b231 100644
--- a/arch/arm/kernel/crunch.c
+++ b/arch/arm/kernel/crunch.c
@@ -15,9 +15,9 @@
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/init.h>
-#include <asm/arch/ep93xx-regs.h>
+#include <linux/io.h>
+#include <mach/ep93xx-regs.h>
#include <asm/thread_notify.h>
-#include <asm/io.h>
struct crunch_state *crunch_owner;
diff --git a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S
index 5617566477b..f53c5829054 100644
--- a/arch/arm/kernel/debug.S
+++ b/arch/arm/kernel/debug.S
@@ -80,7 +80,7 @@
#endif /* CONFIG_CPU_V6 */
#else
-#include <asm/arch/debug-macro.S>
+#include <mach/debug-macro.S>
#endif /* CONFIG_DEBUG_ICEDCC */
/*
@@ -89,10 +89,12 @@
ENTRY(printhex8)
mov r1, #8
b printhex
+ENDPROC(printhex8)
ENTRY(printhex4)
mov r1, #4
b printhex
+ENDPROC(printhex4)
ENTRY(printhex2)
mov r1, #2
@@ -110,6 +112,7 @@ printhex: adr r2, hexbuf
bne 1b
mov r0, r2
b printascii
+ENDPROC(printhex2)
.ltorg
@@ -127,11 +130,13 @@ ENTRY(printascii)
teqne r1, #0
bne 1b
mov pc, lr
+ENDPROC(printascii)
ENTRY(printch)
addruart r3
mov r1, r0
mov r0, #0
b 1b
+ENDPROC(printch)
hexbuf: .space 16
diff --git a/arch/arm/kernel/dma-isa.c b/arch/arm/kernel/dma-isa.c
index 2f080a35a2d..4a3a50495c6 100644
--- a/arch/arm/kernel/dma-isa.c
+++ b/arch/arm/kernel/dma-isa.c
@@ -19,10 +19,9 @@
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
+#include <linux/io.h>
#include <asm/dma.h>
-#include <asm/io.h>
-
#include <asm/mach/dma.h>
#define ISA_DMA_MODE_READ 0x44
diff --git a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c
index ba99a203552..d006085ed7e 100644
--- a/arch/arm/kernel/dma.c
+++ b/arch/arm/kernel/dma.c
@@ -26,23 +26,6 @@ EXPORT_SYMBOL(dma_spin_lock);
static dma_t dma_chan[MAX_DMA_CHANNELS];
/*
- * Get dma list for /proc/dma
- */
-int get_dma_list(char *buf)
-{
- dma_t *dma;
- char *p = buf;
- int i;
-
- for (i = 0, dma = dma_chan; i < MAX_DMA_CHANNELS; i++, dma++)
- if (dma->lock)
- p += sprintf(p, "%2d: %14s %s\n", i,
- dma->d_ops->type, dma->device_id);
-
- return p - buf;
-}
-
-/*
* Request DMA channel
*
* On certain platforms, we have to allocate an interrupt as well...
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index a53c0aba5c1..60c079d8535 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -46,7 +46,7 @@
#include <asm/dma.h>
#include <asm/ecard.h>
-#include <asm/hardware.h>
+#include <mach/hardware.h>
#include <asm/irq.h>
#include <asm/mmu_context.h>
#include <asm/mach/irq.h>
@@ -587,8 +587,7 @@ ecard_irq_handler(unsigned int irq, struct irq_desc *desc)
pending = ecard_default_ops.irqpending(ec);
if (pending) {
- struct irq_desc *d = irq_desc + ec->irq;
- desc_handle_irq(ec->irq, d);
+ generic_handle_irq(ec->irq);
called ++;
}
}
@@ -622,7 +621,6 @@ ecard_irqexp_handler(unsigned int irq, struct irq_desc *desc)
ecard_t *ec = slot_to_ecard(slot);
if (ec->claimed) {
- struct irq_desc *d = irq_desc + ec->irq;
/*
* this ugly code is so that we can operate a
* prioritorising system:
@@ -635,7 +633,7 @@ ecard_irqexp_handler(unsigned int irq, struct irq_desc *desc)
* Serial cards should go in 0/1, ethernet/scsi in 2/3
* otherwise you will lose serial data at high speeds!
*/
- desc_handle_irq(ec->irq, d);
+ generic_handle_irq(ec->irq);
} else {
printk(KERN_WARNING "card%d: interrupt from unclaimed "
"card???\n", slot);
@@ -680,7 +678,7 @@ static int __init ecard_probeirqhw(void)
#define IO_EC_MEMC8_BASE 0
#endif
-unsigned int __ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed)
+static unsigned int __ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed)
{
unsigned long address = 0;
int slot = ec->slot_no;
@@ -783,7 +781,7 @@ static void ecard_proc_init(void)
#define ec_set_resource(ec,nr,st,sz) \
do { \
- (ec)->resource[nr].name = ec->dev.bus_id; \
+ (ec)->resource[nr].name = dev_name(&ec->dev); \
(ec)->resource[nr].start = st; \
(ec)->resource[nr].end = (st) + (sz) - 1; \
(ec)->resource[nr].flags = IORESOURCE_MEM; \
@@ -853,8 +851,7 @@ static struct expansion_card *__init ecard_alloc_card(int type, int slot)
for (i = 0; i < ECARD_NUM_RESOURCES; i++) {
if (ec->resource[i].flags &&
request_resource(&iomem_resource, &ec->resource[i])) {
- printk(KERN_ERR "%s: resource(s) not available\n",
- ec->dev.bus_id);
+ dev_err(&ec->dev, "resource(s) not available\n");
ec->resource[i].end -= ec->resource[i].start;
ec->resource[i].start = 0;
ec->resource[i].flags = 0;
@@ -1002,7 +999,7 @@ ecard_probe(int slot, card_type_t type)
}
rc = -ENODEV;
- if ((ec->podaddr = ecard_address(ec, type, ECARD_SYNC)) == 0)
+ if ((ec->podaddr = __ecard_address(ec, type, ECARD_SYNC)) == 0)
goto nodev;
cid.r_zero = 1;
@@ -1141,10 +1138,10 @@ static int ecard_drv_probe(struct device *dev)
id = ecard_match_device(drv->id_table, ec);
- ecard_claim(ec);
+ ec->claimed = 1;
ret = drv->probe(ec, id);
if (ret)
- ecard_release(ec);
+ ec->claimed = 0;
return ret;
}
@@ -1154,7 +1151,7 @@ static int ecard_drv_remove(struct device *dev)
struct ecard_driver *drv = ECARD_DRV(dev->driver);
drv->remove(ec);
- ecard_release(ec);
+ ec->claimed = 0;
/*
* Restore the default operations. We ensure that the
@@ -1182,7 +1179,7 @@ static void ecard_drv_shutdown(struct device *dev)
if (dev->driver) {
if (drv->shutdown)
drv->shutdown(ec);
- ecard_release(ec);
+ ec->claimed = 0;
}
/*
@@ -1239,7 +1236,6 @@ static int ecard_bus_init(void)
postcore_initcall(ecard_bus_init);
EXPORT_SYMBOL(ecard_readchunk);
-EXPORT_SYMBOL(__ecard_address);
EXPORT_SYMBOL(ecard_register_driver);
EXPORT_SYMBOL(ecard_remove_driver);
EXPORT_SYMBOL(ecard_bus_type);
diff --git a/arch/arm/kernel/ecard.h b/arch/arm/kernel/ecard.h
index d7c2dacf935..4642d436be2 100644
--- a/arch/arm/kernel/ecard.h
+++ b/arch/arm/kernel/ecard.h
@@ -54,3 +54,16 @@ struct ex_chunk_dir {
#define c_len(x) ((x)->r_len[0]|((x)->r_len[1]<<8)|((x)->r_len[2]<<16))
#define c_start(x) ((x)->r_start)
};
+
+typedef enum ecard_type { /* Cards address space */
+ ECARD_IOC,
+ ECARD_MEMC,
+ ECARD_EASI
+} card_type_t;
+
+typedef enum { /* Speed for ECARD_IOC space */
+ ECARD_SLOW = 0,
+ ECARD_MEDIUM = 1,
+ ECARD_FAST = 2,
+ ECARD_SYNC = 3
+} card_speed_t;
diff --git a/arch/arm/kernel/elf.c b/arch/arm/kernel/elf.c
new file mode 100644
index 00000000000..513f332f040
--- /dev/null
+++ b/arch/arm/kernel/elf.c
@@ -0,0 +1,79 @@
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/personality.h>
+#include <linux/binfmts.h>
+#include <linux/elf.h>
+
+int elf_check_arch(const struct elf32_hdr *x)
+{
+ unsigned int eflags;
+
+ /* Make sure it's an ARM executable */
+ if (x->e_machine != EM_ARM)
+ return 0;
+
+ /* Make sure the entry address is reasonable */
+ if (x->e_entry & 1) {
+ if (!(elf_hwcap & HWCAP_THUMB))
+ return 0;
+ } else if (x->e_entry & 3)
+ return 0;
+
+ eflags = x->e_flags;
+ if ((eflags & EF_ARM_EABI_MASK) == EF_ARM_EABI_UNKNOWN) {
+ /* APCS26 is only allowed if the CPU supports it */
+ if ((eflags & EF_ARM_APCS_26) && !(elf_hwcap & HWCAP_26BIT))
+ return 0;
+
+ /* VFP requires the supporting code */
+ if ((eflags & EF_ARM_VFP_FLOAT) && !(elf_hwcap & HWCAP_VFP))
+ return 0;
+ }
+ return 1;
+}
+EXPORT_SYMBOL(elf_check_arch);
+
+void elf_set_personality(const struct elf32_hdr *x)
+{
+ unsigned int eflags = x->e_flags;
+ unsigned int personality = PER_LINUX_32BIT;
+
+ /*
+ * APCS-26 is only valid for OABI executables
+ */
+ if ((eflags & EF_ARM_EABI_MASK) == EF_ARM_EABI_UNKNOWN) {
+ if (eflags & EF_ARM_APCS_26)
+ personality = PER_LINUX;
+ }
+
+ set_personality(personality);
+
+ /*
+ * Since the FPA coprocessor uses CP1 and CP2, and iWMMXt uses CP0
+ * and CP1, we only enable access to the iWMMXt coprocessor if the
+ * binary is EABI or softfloat (and thus, guaranteed not to use
+ * FPA instructions.)
+ */
+ if (elf_hwcap & HWCAP_IWMMXT &&
+ eflags & (EF_ARM_EABI_MASK | EF_ARM_SOFT_FLOAT)) {
+ set_thread_flag(TIF_USING_IWMMXT);
+ } else {
+ clear_thread_flag(TIF_USING_IWMMXT);
+ }
+}
+EXPORT_SYMBOL(elf_set_personality);
+
+/*
+ * Set READ_IMPLIES_EXEC if:
+ * - the binary requires an executable stack
+ * - we're running on a CPU which doesn't support NX.
+ */
+int arm_elf_read_implies_exec(const struct elf32_hdr *x, int executable_stack)
+{
+ if (executable_stack != EXSTACK_ENABLE_X)
+ return 1;
+ if (cpu_architecture() <= CPU_ARCH_ARMv6)
+ return 1;
+ return 0;
+}
+EXPORT_SYMBOL(arm_elf_read_implies_exec);
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 7dca225752c..77b04747553 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -18,7 +18,7 @@
#include <asm/memory.h>
#include <asm/glue.h>
#include <asm/vfpmacros.h>
-#include <asm/arch/entry-macro.S>
+#include <mach/entry-macro.S>
#include <asm/thread_notify.h>
#include "entry-header.S"
@@ -76,14 +76,17 @@
__pabt_invalid:
inv_entry BAD_PREFETCH
b common_invalid
+ENDPROC(__pabt_invalid)
__dabt_invalid:
inv_entry BAD_DATA
b common_invalid
+ENDPROC(__dabt_invalid)
__irq_invalid:
inv_entry BAD_IRQ
b common_invalid
+ENDPROC(__irq_invalid)
__und_invalid:
inv_entry BAD_UNDEFINSTR
@@ -107,6 +110,7 @@ common_invalid:
mov r0, sp
b bad_mode
+ENDPROC(__und_invalid)
/*
* SVC mode handlers
@@ -192,6 +196,7 @@ __dabt_svc:
ldr r0, [sp, #S_PSR]
msr spsr_cxsf, r0
ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
+ENDPROC(__dabt_svc)
.align 5
__irq_svc:
@@ -223,6 +228,7 @@ __irq_svc:
bleq trace_hardirqs_on
#endif
ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
+ENDPROC(__irq_svc)
.ltorg
@@ -272,6 +278,7 @@ __und_svc:
ldr lr, [sp, #S_PSR] @ Get SVC cpsr
msr spsr_cxsf, lr
ldmia sp, {r0 - pc}^ @ Restore SVC registers
+ENDPROC(__und_svc)
.align 5
__pabt_svc:
@@ -313,6 +320,7 @@ __pabt_svc:
ldr r0, [sp, #S_PSR]
msr spsr_cxsf, r0
ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
+ENDPROC(__pabt_svc)
.align 5
.LCcralign:
@@ -412,6 +420,7 @@ __dabt_usr:
mov r2, sp
adr lr, ret_from_exception
b do_DataAbort
+ENDPROC(__dabt_usr)
.align 5
__irq_usr:
@@ -441,6 +450,7 @@ __irq_usr:
mov why, #0
b ret_to_user
+ENDPROC(__irq_usr)
.ltorg
@@ -474,6 +484,7 @@ __und_usr:
#else
b __und_usr_unknown
#endif
+ENDPROC(__und_usr)
@
@ fallthrough to call_fpe
@@ -642,6 +653,7 @@ __und_usr_unknown:
mov r0, sp
adr lr, ret_from_exception
b do_undefinstr
+ENDPROC(__und_usr_unknown)
.align 5
__pabt_usr:
@@ -666,6 +678,8 @@ ENTRY(ret_from_exception)
get_thread_info tsk
mov why, #0
b ret_to_user
+ENDPROC(__pabt_usr)
+ENDPROC(ret_from_exception)
/*
* Register switch for ARMv3 and ARMv4 processors
@@ -702,6 +716,7 @@ ENTRY(__switch_to)
bl atomic_notifier_call_chain
mov r0, r5
ldmia r4, {r4 - sl, fp, sp, pc} @ Load all regs saved previously
+ENDPROC(__switch_to)
__INIT
@@ -1029,6 +1044,7 @@ vector_\name:
mov r0, sp
ldr lr, [pc, lr, lsl #2]
movs pc, lr @ branch to handler in SVC mode
+ENDPROC(vector_\name)
.endm
.globl __stubs_start
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 597ed00a08d..3aa14dcc5ba 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -9,7 +9,8 @@
*/
#include <asm/unistd.h>
-#include <asm/arch/entry-macro.S>
+#include <asm/ftrace.h>
+#include <mach/entry-macro.S>
#include "entry-header.S"
@@ -76,6 +77,7 @@ no_work_pending:
mov r0, r0
add sp, sp, #S_FRAME_SIZE - S_PC
movs pc, lr @ return & move spsr_svc into cpsr
+ENDPROC(ret_to_user)
/*
* This is how we return from a fork.
@@ -91,7 +93,7 @@ ENTRY(ret_from_fork)
mov r0, #1 @ trace exit [IP = 1]
bl syscall_trace
b ret_slow_syscall
-
+ENDPROC(ret_from_fork)
.equ NR_syscalls,0
#define CALL(x) .equ NR_syscalls,NR_syscalls+1
@@ -99,6 +101,56 @@ ENTRY(ret_from_fork)
#undef CALL
#define CALL(x) .long x
+#ifdef CONFIG_FTRACE
+#ifdef CONFIG_DYNAMIC_FTRACE
+ENTRY(mcount)
+ stmdb sp!, {r0-r3, lr}
+ mov r0, lr
+ sub r0, r0, #MCOUNT_INSN_SIZE
+
+ .globl mcount_call
+mcount_call:
+ bl ftrace_stub
+ ldmia sp!, {r0-r3, pc}
+
+ENTRY(ftrace_caller)
+ stmdb sp!, {r0-r3, lr}
+ ldr r1, [fp, #-4]
+ mov r0, lr
+ sub r0, r0, #MCOUNT_INSN_SIZE
+
+ .globl ftrace_call
+ftrace_call:
+ bl ftrace_stub
+ ldmia sp!, {r0-r3, pc}
+
+#else
+
+ENTRY(mcount)
+ stmdb sp!, {r0-r3, lr}
+ ldr r0, =ftrace_trace_function
+ ldr r2, [r0]
+ adr r0, ftrace_stub
+ cmp r0, r2
+ bne trace
+ ldmia sp!, {r0-r3, pc}
+
+trace:
+ ldr r1, [fp, #-4]
+ mov r0, lr
+ sub r0, r0, #MCOUNT_INSN_SIZE
+ mov lr, pc
+ mov pc, r2
+ ldmia sp!, {r0-r3, pc}
+
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
+ .globl ftrace_stub
+ftrace_stub:
+ mov pc, lr
+
+#endif /* CONFIG_FTRACE */
+
/*=============================================================================
* SWI handler
*-----------------------------------------------------------------------------
@@ -218,6 +270,7 @@ ENTRY(vector_swi)
eor r0, scno, #__NR_SYSCALL_BASE @ put OS number back
bcs arm_syscall
b sys_ni_syscall @ not private func
+ENDPROC(vector_swi)
/*
* This is the really slow path. We're going to be doing
@@ -275,7 +328,6 @@ ENTRY(sys_call_table)
*/
@ r0 = syscall number
@ r8 = syscall table
- .type sys_syscall, #function
sys_syscall:
bic scno, r0, #__NR_OABI_SYSCALL_BASE
cmp scno, #__NR_syscall - __NR_SYSCALL_BASE
@@ -287,53 +339,65 @@ sys_syscall:
movlo r3, r4
ldrlo pc, [tbl, scno, lsl #2]
b sys_ni_syscall
+ENDPROC(sys_syscall)
sys_fork_wrapper:
add r0, sp, #S_OFF
b sys_fork
+ENDPROC(sys_fork_wrapper)
sys_vfork_wrapper:
add r0, sp, #S_OFF
b sys_vfork
+ENDPROC(sys_vfork_wrapper)
sys_execve_wrapper:
add r3, sp, #S_OFF
b sys_execve
+ENDPROC(sys_execve_wrapper)
sys_clone_wrapper:
add ip, sp, #S_OFF
str ip, [sp, #4]
b sys_clone
+ENDPROC(sys_clone_wrapper)
sys_sigsuspend_wrapper:
add r3, sp, #S_OFF
b sys_sigsuspend
+ENDPROC(sys_sigsuspend_wrapper)
sys_rt_sigsuspend_wrapper:
add r2, sp, #S_OFF
b sys_rt_sigsuspend
+ENDPROC(sys_rt_sigsuspend_wrapper)
sys_sigreturn_wrapper:
add r0, sp, #S_OFF
b sys_sigreturn
+ENDPROC(sys_sigreturn_wrapper)
sys_rt_sigreturn_wrapper:
add r0, sp, #S_OFF
b sys_rt_sigreturn
+ENDPROC(sys_rt_sigreturn_wrapper)
sys_sigaltstack_wrapper:
ldr r2, [sp, #S_OFF + S_SP]
b do_sigaltstack
+ENDPROC(sys_sigaltstack_wrapper)
sys_statfs64_wrapper:
teq r1, #88
moveq r1, #84
b sys_statfs64
+ENDPROC(sys_statfs64_wrapper)
sys_fstatfs64_wrapper:
teq r1, #88
moveq r1, #84
b sys_fstatfs64
+ENDPROC(sys_fstatfs64_wrapper)
/*
* Note: off_4k (r5) is always units of 4K. If we can't do the requested
@@ -351,11 +415,14 @@ sys_mmap2:
str r5, [sp, #4]
b do_mmap2
#endif
+ENDPROC(sys_mmap2)
ENTRY(pabort_ifar)
mrc p15, 0, r0, cr6, cr0, 2
ENTRY(pabort_noifar)
mov pc, lr
+ENDPROC(pabort_ifar)
+ENDPROC(pabort_noifar)
#ifdef CONFIG_OABI_COMPAT
@@ -366,26 +433,31 @@ ENTRY(pabort_noifar)
sys_oabi_pread64:
stmia sp, {r3, r4}
b sys_pread64
+ENDPROC(sys_oabi_pread64)
sys_oabi_pwrite64:
stmia sp, {r3, r4}
b sys_pwrite64
+ENDPROC(sys_oabi_pwrite64)
sys_oabi_truncate64:
mov r3, r2
mov r2, r1
b sys_truncate64
+ENDPROC(sys_oabi_truncate64)
sys_oabi_ftruncate64:
mov r3, r2
mov r2, r1
b sys_ftruncate64
+ENDPROC(sys_oabi_ftruncate64)
sys_oabi_readahead:
str r3, [sp]
mov r3, r2
mov r2, r1
b sys_readahead
+ENDPROC(sys_oabi_readahead)
/*
* Let's declare a second syscall table for old ABI binaries
diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c
index e8e90346f11..36f81d96797 100644
--- a/arch/arm/kernel/fiq.c
+++ b/arch/arm/kernel/fiq.c
@@ -45,7 +45,6 @@
#include <asm/fiq.h>
#include <asm/irq.h>
#include <asm/system.h>
-#include <asm/uaccess.h>
static unsigned long no_fiq_insn;
diff --git a/arch/arm/kernel/ftrace.c b/arch/arm/kernel/ftrace.c
new file mode 100644
index 00000000000..76d50e6091b
--- /dev/null
+++ b/arch/arm/kernel/ftrace.c
@@ -0,0 +1,116 @@
+/*
+ * Dynamic function tracing support.
+ *
+ * Copyright (C) 2008 Abhishek Sagar <sagar.abhishek@gmail.com>
+ *
+ * For licencing details, see COPYING.
+ *
+ * Defines low-level handling of mcount calls when the kernel
+ * is compiled with the -pg flag. When using dynamic ftrace, the
+ * mcount call-sites get patched lazily with NOP till they are
+ * enabled. All code mutation routines here take effect atomically.
+ */
+
+#include <linux/ftrace.h>
+
+#include <asm/cacheflush.h>
+#include <asm/ftrace.h>
+
+#define PC_OFFSET 8
+#define BL_OPCODE 0xeb000000
+#define BL_OFFSET_MASK 0x00ffffff
+
+static unsigned long bl_insn;
+static const unsigned long NOP = 0xe1a00000; /* mov r0, r0 */
+
+unsigned char *ftrace_nop_replace(void)
+{
+ return (char *)&NOP;
+}
+
+/* construct a branch (BL) instruction to addr */
+unsigned char *ftrace_call_replace(unsigned long pc, unsigned long addr)
+{
+ long offset;
+
+ offset = (long)addr - (long)(pc + PC_OFFSET);
+ if (unlikely(offset < -33554432 || offset > 33554428)) {
+ /* Can't generate branches that far (from ARM ARM). Ftrace
+ * doesn't generate branches outside of kernel text.
+ */
+ WARN_ON_ONCE(1);
+ return NULL;
+ }
+ offset = (offset >> 2) & BL_OFFSET_MASK;
+ bl_insn = BL_OPCODE | offset;
+ return (unsigned char *)&bl_insn;
+}
+
+int ftrace_modify_code(unsigned long pc, unsigned char *old_code,
+ unsigned char *new_code)
+{
+ unsigned long err = 0, replaced = 0, old, new;
+
+ old = *(unsigned long *)old_code;
+ new = *(unsigned long *)new_code;
+
+ __asm__ __volatile__ (
+ "1: ldr %1, [%2] \n"
+ " cmp %1, %4 \n"
+ "2: streq %3, [%2] \n"
+ " cmpne %1, %3 \n"
+ " movne %0, #2 \n"
+ "3:\n"
+
+ ".section .fixup, \"ax\"\n"
+ "4: mov %0, #1 \n"
+ " b 3b \n"
+ ".previous\n"
+
+ ".section __ex_table, \"a\"\n"
+ " .long 1b, 4b \n"
+ " .long 2b, 4b \n"
+ ".previous\n"
+
+ : "=r"(err), "=r"(replaced)
+ : "r"(pc), "r"(new), "r"(old), "0"(err), "1"(replaced)
+ : "memory");
+
+ if (!err && (replaced == old))
+ flush_icache_range(pc, pc + MCOUNT_INSN_SIZE);
+
+ return err;
+}
+
+int ftrace_update_ftrace_func(ftrace_func_t func)
+{
+ int ret;
+ unsigned long pc, old;
+ unsigned char *new;
+
+ pc = (unsigned long)&ftrace_call;
+ memcpy(&old, &ftrace_call, MCOUNT_INSN_SIZE);
+ new = ftrace_call_replace(pc, (unsigned long)func);
+ ret = ftrace_modify_code(pc, (unsigned char *)&old, new);
+ return ret;
+}
+
+int ftrace_mcount_set(unsigned long *data)
+{
+ unsigned long pc, old;
+ unsigned long *addr = data;
+ unsigned char *new;
+
+ pc = (unsigned long)&mcount_call;
+ memcpy(&old, &mcount_call, MCOUNT_INSN_SIZE);
+ new = ftrace_call_replace(pc, *addr);
+ *addr = ftrace_modify_code(pc, (unsigned char *)&old, new);
+ return 0;
+}
+
+/* run from kstop_machine */
+int __init ftrace_dyn_arch_init(void *data)
+{
+ ftrace_mcount_set(data);
+ return 0;
+}
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
index 7e9c00a8a41..bde52df1c66 100644
--- a/arch/arm/kernel/head-common.S
+++ b/arch/arm/kernel/head-common.S
@@ -36,7 +36,6 @@ __switch_data:
* r2 = atags pointer
* r9 = processor ID
*/
- .type __mmap_switched, %function
__mmap_switched:
adr r3, __switch_data + 4
@@ -59,6 +58,7 @@ __mmap_switched:
bic r4, r0, #CR_A @ Clear 'A' bit
stmia r7, {r0, r4} @ Save control register values
b start_kernel
+ENDPROC(__mmap_switched)
/*
* Exception handling. Something went wrong and we can't proceed. We
@@ -69,8 +69,6 @@ __mmap_switched:
* and hope for the best (useful if bootloader fails to pass a proper
* machine ID for example).
*/
-
- .type __error_p, %function
__error_p:
#ifdef CONFIG_DEBUG_LL
adr r0, str_p1
@@ -84,8 +82,8 @@ str_p1: .asciz "\nError: unrecognized/unsupported processor variant (0x"
str_p2: .asciz ").\n"
.align
#endif
+ENDPROC(__error_p)
- .type __error_a, %function
__error_a:
#ifdef CONFIG_DEBUG_LL
mov r4, r1 @ preserve machine ID
@@ -115,13 +113,14 @@ __error_a:
adr r0, str_a3
bl printascii
b __error
+ENDPROC(__error_a)
+
str_a1: .asciz "\nError: unrecognized/unsupported machine ID (r1 = 0x"
str_a2: .asciz ").\n\nAvailable machine support:\n\nID (hex)\tNAME\n"
str_a3: .asciz "\nPlease check your kernel config and/or bootloader.\n"
.align
#endif
- .type __error, %function
__error:
#ifdef CONFIG_ARCH_RPC
/*
@@ -138,6 +137,7 @@ __error:
#endif
1: mov r0, r0
b 1b
+ENDPROC(__error)
/*
@@ -153,7 +153,6 @@ __error:
* r5 = proc_info pointer in physical address space
* r9 = cpuid (preserved)
*/
- .type __lookup_processor_type, %function
__lookup_processor_type:
adr r3, 3f
ldmda r3, {r5 - r7}
@@ -169,6 +168,7 @@ __lookup_processor_type:
blo 1b
mov r5, #0 @ unknown processor
2: mov pc, lr
+ENDPROC(__lookup_processor_type)
/*
* This provides a C-API version of the above function.
@@ -179,9 +179,10 @@ ENTRY(lookup_processor_type)
bl __lookup_processor_type
mov r0, r5
ldmfd sp!, {r4 - r7, r9, pc}
+ENDPROC(lookup_processor_type)
/*
- * Look in include/asm-arm/procinfo.h and arch/arm/kernel/arch.[ch] for
+ * Look in <asm/procinfo.h> and arch/arm/kernel/arch.[ch] for
* more information about the __proc_info and __arch_info structures.
*/
.long __proc_info_begin
@@ -201,7 +202,6 @@ ENTRY(lookup_processor_type)
* r3, r4, r6 corrupted
* r5 = mach_info pointer in physical address space
*/
- .type __lookup_machine_type, %function
__lookup_machine_type:
adr r3, 3b
ldmia r3, {r4, r5, r6}
@@ -216,6 +216,7 @@ __lookup_machine_type:
blo 1b
mov r5, #0 @ unknown machine
2: mov pc, lr
+ENDPROC(__lookup_machine_type)
/*
* This provides a C-API version of the above function.
@@ -226,6 +227,7 @@ ENTRY(lookup_machine_type)
bl __lookup_machine_type
mov r0, r5
ldmfd sp!, {r4 - r6, pc}
+ENDPROC(lookup_machine_type)
/* Determine validity of the r2 atags pointer. The heuristic requires
* that the pointer be aligned, in the first 16k of physical RAM and
@@ -239,8 +241,6 @@ ENTRY(lookup_machine_type)
* r2 either valid atags pointer, or zero
* r5, r6 corrupted
*/
-
- .type __vet_atags, %function
__vet_atags:
tst r2, #0x3 @ aligned?
bne 1f
@@ -257,3 +257,4 @@ __vet_atags:
1: mov r2, #0
mov pc, lr
+ENDPROC(__vet_atags)
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index 5d78ffb8a9a..cc87e1765ed 100644
--- a/arch/arm/kernel/head-nommu.S
+++ b/arch/arm/kernel/head-nommu.S
@@ -15,7 +15,6 @@
#include <linux/init.h>
#include <asm/assembler.h>
-#include <asm/mach-types.h>
#include <asm/ptrace.h>
#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
@@ -34,7 +33,6 @@
*
*/
.section ".text.head", "ax"
- .type stext, %function
ENTRY(stext)
msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode
@ and irqs disabled
@@ -54,11 +52,11 @@ ENTRY(stext)
@ the initialization is done
adr lr, __after_proc_init @ return (PIC) address
add pc, r10, #PROCINFO_INITFUNC
+ENDPROC(stext)
/*
* Set the Control Register and Read the process ID.
*/
- .type __after_proc_init, %function
__after_proc_init:
#ifdef CONFIG_CPU_CP15
mrc p15, 0, r0, c1, c0, 0 @ read control reg
@@ -86,6 +84,7 @@ __after_proc_init:
mov pc, r13 @ clear the BSS and jump
@ to start_kernel
+ENDPROC(__after_proc_init)
.ltorg
#include "head-common.S"
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index bff4c6e90dd..21e17dc94cb 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -75,7 +75,6 @@
* circumstances, zImage) is for.
*/
.section ".text.head", "ax"
- .type stext, %function
ENTRY(stext)
msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode
@ and irqs disabled
@@ -100,9 +99,9 @@ ENTRY(stext)
@ mmu has been enabled
adr lr, __enable_mmu @ return (PIC) address
add pc, r10, #PROCINFO_INITFUNC
+ENDPROC(stext)
#if defined(CONFIG_SMP)
- .type secondary_startup, #function
ENTRY(secondary_startup)
/*
* Common entry point for secondary CPUs.
@@ -128,6 +127,7 @@ ENTRY(secondary_startup)
adr lr, __enable_mmu @ return address
add pc, r10, #PROCINFO_INITFUNC @ initialise processor
@ (return control reg)
+ENDPROC(secondary_startup)
/*
* r6 = &secondary_data
@@ -136,6 +136,7 @@ ENTRY(__secondary_switched)
ldr sp, [r7, #4] @ get secondary_data.stack
mov fp, #0
b secondary_start_kernel
+ENDPROC(__secondary_switched)
.type __secondary_data, %object
__secondary_data:
@@ -151,7 +152,6 @@ __secondary_data:
* this is just loading the page table pointer and domain access
* registers.
*/
- .type __enable_mmu, %function
__enable_mmu:
#ifdef CONFIG_ALIGNMENT_TRAP
orr r0, r0, #CR_A
@@ -174,6 +174,7 @@ __enable_mmu:
mcr p15, 0, r5, c3, c0, 0 @ load domain access register
mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
b __turn_mmu_on
+ENDPROC(__enable_mmu)
/*
* Enable the MMU. This completely changes the structure of the visible
@@ -187,7 +188,6 @@ __enable_mmu:
* other registers depend on the function called upon completion
*/
.align 5
- .type __turn_mmu_on, %function
__turn_mmu_on:
mov r0, r0
mcr p15, 0, r0, c1, c0, 0 @ write control reg
@@ -195,7 +195,7 @@ __turn_mmu_on:
mov r3, r3
mov r3, r3
mov pc, r13
-
+ENDPROC(__turn_mmu_on)
/*
@@ -211,7 +211,6 @@ __turn_mmu_on:
* r0, r3, r6, r7 corrupted
* r4 = physical page table address
*/
- .type __create_page_tables, %function
__create_page_tables:
pgtbl r4 @ page table address
@@ -325,6 +324,7 @@ __create_page_tables:
#endif
#endif
mov pc, lr
+ENDPROC(__create_page_tables)
.ltorg
#include "head-common.S"
diff --git a/arch/arm/kernel/init_task.c b/arch/arm/kernel/init_task.c
index 8b8c9d38a76..0bbf8062539 100644
--- a/arch/arm/kernel/init_task.c
+++ b/arch/arm/kernel/init_task.c
@@ -8,8 +8,8 @@
#include <linux/init.h>
#include <linux/init_task.h>
#include <linux/mqueue.h>
+#include <linux/uaccess.h>
-#include <asm/uaccess.h>
#include <asm/pgtable.h>
static struct fs_struct init_fs = INIT_FS;
diff --git a/arch/arm/kernel/io.c b/arch/arm/kernel/io.c
index 1f6822dfae7..f4470307edb 100644
--- a/arch/arm/kernel/io.c
+++ b/arch/arm/kernel/io.c
@@ -1,7 +1,6 @@
#include <linux/module.h>
#include <linux/types.h>
-
-#include <asm/io.h>
+#include <linux/io.h>
/*
* Copy data from IO memory space to "real" memory space.
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 11dcd52e51b..2f3eb795fa6 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -38,6 +38,7 @@
#include <linux/proc_fs.h>
#include <asm/system.h>
+#include <asm/mach/irq.h>
#include <asm/mach/time.h>
/*
@@ -111,18 +112,17 @@ static struct irq_desc bad_irq_desc = {
asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
- struct irq_desc *desc = irq_desc + irq;
+
+ irq_enter();
/*
* Some hardware gives randomly wrong interrupts. Rather
* than crashing, do something sensible.
*/
if (irq >= NR_IRQS)
- desc = &bad_irq_desc;
-
- irq_enter();
-
- desc_handle_irq(irq, desc);
+ handle_bad_irq(irq, &bad_irq_desc);
+ else
+ generic_handle_irq(irq);
/* AT91 specific workaround */
irq_finish(irq);
diff --git a/arch/arm/kernel/kgdb.c b/arch/arm/kernel/kgdb.c
new file mode 100644
index 00000000000..ba8ccfede96
--- /dev/null
+++ b/arch/arm/kernel/kgdb.c
@@ -0,0 +1,199 @@
+/*
+ * arch/arm/kernel/kgdb.c
+ *
+ * ARM KGDB support
+ *
+ * Copyright (c) 2002-2004 MontaVista Software, Inc
+ * Copyright (c) 2008 Wind River Systems, Inc.
+ *
+ * Authors: George Davis <davis_g@mvista.com>
+ * Deepak Saxena <dsaxena@plexity.net>
+ */
+#include <linux/kgdb.h>
+#include <asm/traps.h>
+
+/* Make a local copy of the registers passed into the handler (bletch) */
+void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *kernel_regs)
+{
+ int regno;
+
+ /* Initialize all to zero. */
+ for (regno = 0; regno < GDB_MAX_REGS; regno++)
+ gdb_regs[regno] = 0;
+
+ gdb_regs[_R0] = kernel_regs->ARM_r0;
+ gdb_regs[_R1] = kernel_regs->ARM_r1;
+ gdb_regs[_R2] = kernel_regs->ARM_r2;
+ gdb_regs[_R3] = kernel_regs->ARM_r3;
+ gdb_regs[_R4] = kernel_regs->ARM_r4;
+ gdb_regs[_R5] = kernel_regs->ARM_r5;
+ gdb_regs[_R6] = kernel_regs->ARM_r6;
+ gdb_regs[_R7] = kernel_regs->ARM_r7;
+ gdb_regs[_R8] = kernel_regs->ARM_r8;
+ gdb_regs[_R9] = kernel_regs->ARM_r9;
+ gdb_regs[_R10] = kernel_regs->ARM_r10;
+ gdb_regs[_FP] = kernel_regs->ARM_fp;
+ gdb_regs[_IP] = kernel_regs->ARM_ip;
+ gdb_regs[_SPT] = kernel_regs->ARM_sp;
+ gdb_regs[_LR] = kernel_regs->ARM_lr;
+ gdb_regs[_PC] = kernel_regs->ARM_pc;
+ gdb_regs[_CPSR] = kernel_regs->ARM_cpsr;
+}
+
+/* Copy local gdb registers back to kgdb regs, for later copy to kernel */
+void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *kernel_regs)
+{
+ kernel_regs->ARM_r0 = gdb_regs[_R0];
+ kernel_regs->ARM_r1 = gdb_regs[_R1];
+ kernel_regs->ARM_r2 = gdb_regs[_R2];
+ kernel_regs->ARM_r3 = gdb_regs[_R3];
+ kernel_regs->ARM_r4 = gdb_regs[_R4];
+ kernel_regs->ARM_r5 = gdb_regs[_R5];
+ kernel_regs->ARM_r6 = gdb_regs[_R6];
+ kernel_regs->ARM_r7 = gdb_regs[_R7];
+ kernel_regs->ARM_r8 = gdb_regs[_R8];
+ kernel_regs->ARM_r9 = gdb_regs[_R9];
+ kernel_regs->ARM_r10 = gdb_regs[_R10];
+ kernel_regs->ARM_fp = gdb_regs[_FP];
+ kernel_regs->ARM_ip = gdb_regs[_IP];
+ kernel_regs->ARM_sp = gdb_regs[_SPT];
+ kernel_regs->ARM_lr = gdb_regs[_LR];
+ kernel_regs->ARM_pc = gdb_regs[_PC];
+ kernel_regs->ARM_cpsr = gdb_regs[_CPSR];
+}
+
+void
+sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *task)
+{
+ struct pt_regs *thread_regs;
+ int regno;
+
+ /* Just making sure... */
+ if (task == NULL)
+ return;
+
+ /* Initialize to zero */
+ for (regno = 0; regno < GDB_MAX_REGS; regno++)
+ gdb_regs[regno] = 0;
+
+ /* Otherwise, we have only some registers from switch_to() */
+ thread_regs = task_pt_regs(task);
+ gdb_regs[_R0] = thread_regs->ARM_r0;
+ gdb_regs[_R1] = thread_regs->ARM_r1;
+ gdb_regs[_R2] = thread_regs->ARM_r2;
+ gdb_regs[_R3] = thread_regs->ARM_r3;
+ gdb_regs[_R4] = thread_regs->ARM_r4;
+ gdb_regs[_R5] = thread_regs->ARM_r5;
+ gdb_regs[_R6] = thread_regs->ARM_r6;
+ gdb_regs[_R7] = thread_regs->ARM_r7;
+ gdb_regs[_R8] = thread_regs->ARM_r8;
+ gdb_regs[_R9] = thread_regs->ARM_r9;
+ gdb_regs[_R10] = thread_regs->ARM_r10;
+ gdb_regs[_FP] = thread_regs->ARM_fp;
+ gdb_regs[_IP] = thread_regs->ARM_ip;
+ gdb_regs[_SPT] = thread_regs->ARM_sp;
+ gdb_regs[_LR] = thread_regs->ARM_lr;
+ gdb_regs[_PC] = thread_regs->ARM_pc;
+ gdb_regs[_CPSR] = thread_regs->ARM_cpsr;
+}
+
+static int compiled_break;
+
+int kgdb_arch_handle_exception(int exception_vector, int signo,
+ int err_code, char *remcom_in_buffer,
+ char *remcom_out_buffer,
+ struct pt_regs *linux_regs)
+{
+ unsigned long addr;
+ char *ptr;
+
+ switch (remcom_in_buffer[0]) {
+ case 'D':
+ case 'k':
+ case 'c':
+ /*
+ * Try to read optional parameter, pc unchanged if no parm.
+ * If this was a compiled breakpoint, we need to move
+ * to the next instruction or we will just breakpoint
+ * over and over again.
+ */
+ ptr = &remcom_in_buffer[1];
+ if (kgdb_hex2long(&ptr, &addr))
+ linux_regs->ARM_pc = addr;
+ else if (compiled_break == 1)
+ linux_regs->ARM_pc += 4;
+
+ compiled_break = 0;
+
+ return 0;
+ }
+
+ return -1;
+}
+
+static int kgdb_brk_fn(struct pt_regs *regs, unsigned int instr)
+{
+ kgdb_handle_exception(1, SIGTRAP, 0, regs);
+
+ return 0;
+}
+
+static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned int instr)
+{
+ compiled_break = 1;
+ kgdb_handle_exception(1, SIGTRAP, 0, regs);
+
+ return 0;
+}
+
+static struct undef_hook kgdb_brkpt_hook = {
+ .instr_mask = 0xffffffff,
+ .instr_val = KGDB_BREAKINST,
+ .fn = kgdb_brk_fn
+};
+
+static struct undef_hook kgdb_compiled_brkpt_hook = {
+ .instr_mask = 0xffffffff,
+ .instr_val = KGDB_COMPILED_BREAK,
+ .fn = kgdb_compiled_brk_fn
+};
+
+/**
+ * kgdb_arch_init - Perform any architecture specific initalization.
+ *
+ * This function will handle the initalization of any architecture
+ * specific callbacks.
+ */
+int kgdb_arch_init(void)
+{
+ register_undef_hook(&kgdb_brkpt_hook);
+ register_undef_hook(&kgdb_compiled_brkpt_hook);
+
+ return 0;
+}
+
+/**
+ * kgdb_arch_exit - Perform any architecture specific uninitalization.
+ *
+ * This function will handle the uninitalization of any architecture
+ * specific callbacks, for dynamic registration and unregistration.
+ */
+void kgdb_arch_exit(void)
+{
+ unregister_undef_hook(&kgdb_brkpt_hook);
+ unregister_undef_hook(&kgdb_compiled_brkpt_hook);
+}
+
+/*
+ * Register our undef instruction hooks with ARM undef core.
+ * We regsiter a hook specifically looking for the KGB break inst
+ * and we handle the normal undef case within the do_undefinstr
+ * handler.
+ */
+struct kgdb_arch arch_kgdb_ops = {
+#ifndef __ARMEB__
+ .gdb_bpt_instr = {0xfe, 0xde, 0xff, 0xe7}
+#else /* ! __ARMEB__ */
+ .gdb_bpt_instr = {0xe7, 0xff, 0xde, 0xfe}
+#endif
+};
diff --git a/arch/arm/kernel/kprobes-decode.c b/arch/arm/kernel/kprobes-decode.c
index b4565bb133c..da1f94906a4 100644
--- a/arch/arm/kernel/kprobes-decode.c
+++ b/arch/arm/kernel/kprobes-decode.c
@@ -488,7 +488,7 @@ static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs)
if (!ubit)
addr -= reg_count;
- addr += (!pbit ^ !ubit);
+ addr += (!pbit == !ubit);
reg_bit_vector = insn & 0xffff;
while (reg_bit_vector) {
@@ -503,7 +503,7 @@ static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs)
if (wbit) {
if (!ubit)
addr -= reg_count;
- addr -= (!pbit ^ !ubit);
+ addr -= (!pbit == !ubit);
regs->uregs[rn] = (long)addr;
}
}
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
index 5593dd20721..3f9abe0e9af 100644
--- a/arch/arm/kernel/kprobes.c
+++ b/arch/arm/kernel/kprobes.c
@@ -200,9 +200,12 @@ void __kprobes kprobe_handler(struct pt_regs *regs)
}
}
-int kprobe_trap_handler(struct pt_regs *regs, unsigned int instr)
+static int __kprobes kprobe_trap_handler(struct pt_regs *regs, unsigned int instr)
{
+ unsigned long flags;
+ local_irq_save(flags);
kprobe_handler(regs);
+ local_irq_restore(flags);
return 0;
}
@@ -274,7 +277,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
* for kretprobe handlers which should normally be interested in r0 only
* anyway.
*/
-static void __attribute__((naked)) __kprobes kretprobe_trampoline(void)
+void __naked __kprobes kretprobe_trampoline(void)
{
__asm__ __volatile__ (
"stmdb sp!, {r0 - r11} \n\t"
@@ -296,8 +299,7 @@ static __used __kprobes void *trampoline_handler(struct pt_regs *regs)
unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline;
INIT_HLIST_HEAD(&empty_rp);
- spin_lock_irqsave(&kretprobe_lock, flags);
- head = kretprobe_inst_table_head(current);
+ kretprobe_hash_lock(current, &head, &flags);
/*
* It is possible to have multiple instances associated with a given
@@ -337,7 +339,7 @@ static __used __kprobes void *trampoline_handler(struct pt_regs *regs)
}
kretprobe_assert(ri, orig_ret_address, trampoline_address);
- spin_unlock_irqrestore(&kretprobe_lock, flags);
+ kretprobe_hash_unlock(current, &flags);
hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
hlist_del(&ri->hlist);
@@ -347,7 +349,6 @@ static __used __kprobes void *trampoline_handler(struct pt_regs *regs)
return (void *)orig_ret_address;
}
-/* Called with kretprobe_lock held. */
void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
struct pt_regs *regs)
{
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
index db8f54a3451..440dc62cdc3 100644
--- a/arch/arm/kernel/machine_kexec.c
+++ b/arch/arm/kernel/machine_kexec.c
@@ -6,10 +6,10 @@
#include <linux/kexec.h>
#include <linux/delay.h>
#include <linux/reboot.h>
+#include <linux/io.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
#include <asm/mmu_context.h>
-#include <asm/io.h>
#include <asm/cacheflush.h>
#include <asm/mach-types.h>
@@ -71,7 +71,7 @@ void machine_kexec(struct kimage *image)
flush_icache_range((unsigned long) reboot_code_buffer,
- (unsigned long) reboot_code_buffer + KEXEC_CONTROL_CODE_SIZE);
+ (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE);
printk(KERN_INFO "Bye!\n");
cpu_proc_fin();
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index 79b7e5cf541..9203ba7d58e 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/moduleloader.h>
#include <linux/kernel.h>
+#include <linux/mm.h>
#include <linux/elf.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
@@ -46,7 +47,7 @@ void *module_alloc(unsigned long size)
if (!area)
return NULL;
- return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL);
+ return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL_EXEC);
}
#else /* CONFIG_MMU */
void *module_alloc(unsigned long size)
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 46bf2ede612..d3ea6fa8952 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -28,12 +28,12 @@
#include <linux/pm.h>
#include <linux/tick.h>
#include <linux/utsname.h>
+#include <linux/uaccess.h>
#include <asm/leds.h>
#include <asm/processor.h>
#include <asm/system.h>
#include <asm/thread_notify.h>
-#include <asm/uaccess.h>
#include <asm/mach/time.h>
static const char *processor_modes[] = {
@@ -51,7 +51,7 @@ extern void setup_mm_for_reboot(char mode);
static volatile int hlt_counter;
-#include <asm/arch/system.h>
+#include <mach/system.h>
void disable_hlt(void)
{
@@ -133,10 +133,8 @@ static void default_idle(void)
cpu_relax();
else {
local_irq_disable();
- if (!need_resched()) {
- timer_dyn_reprogram();
+ if (!need_resched())
arch_idle();
- }
local_irq_enable();
}
}
@@ -164,7 +162,7 @@ void cpu_idle(void)
if (!idle)
idle = default_idle;
leds_event(led_idle_start);
- tick_nohz_stop_sched_tick();
+ tick_nohz_stop_sched_tick(1);
while (!need_resched())
idle();
leds_event(led_idle_end);
@@ -269,35 +267,6 @@ void show_regs(struct pt_regs * regs)
__backtrace();
}
-void show_fpregs(struct user_fp *regs)
-{
- int i;
-
- for (i = 0; i < 8; i++) {
- unsigned long *p;
- char type;
-
- p = (unsigned long *)(regs->fpregs + i);
-
- switch (regs->ftype[i]) {
- case 1: type = 'f'; break;
- case 2: type = 'd'; break;
- case 3: type = 'e'; break;
- default: type = '?'; break;
- }
- if (regs->init_flag)
- type = '?';
-
- printk(" f%d(%c): %08lx %08lx %08lx%c",
- i, type, p[0], p[1], p[2], i & 1 ? '\n' : ' ');
- }
-
-
- printk("FPSR: %08lx FPCR: %08lx\n",
- (unsigned long)regs->fpsr,
- (unsigned long)regs->fpcr);
-}
-
/*
* Free current thread data structures etc..
*/
@@ -416,7 +385,7 @@ unsigned long get_wchan(struct task_struct *p)
do {
if (fp < stack_start || fp > stack_end)
return 0;
- lr = pc_pointer (((unsigned long *)fp)[-1]);
+ lr = ((unsigned long *)fp)[-1];
if (!in_sched_functions(lr))
return lr;
fp = *(unsigned long *) (fp - 12);
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 4b05dc5c102..df653ea5925 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -18,8 +18,8 @@
#include <linux/security.h>
#include <linux/init.h>
#include <linux/signal.h>
+#include <linux/uaccess.h>
-#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/system.h>
#include <asm/traps.h>
@@ -126,7 +126,7 @@ ptrace_getrn(struct task_struct *child, unsigned long insn)
val = get_user_reg(child, reg);
if (reg == 15)
- val = pc_pointer(val + 8);
+ val += 8;
return val;
}
@@ -278,8 +278,7 @@ get_branch_address(struct task_struct *child, unsigned long pc, unsigned long in
else
base -= aluop2;
}
- if (read_u32(child, base, &alt) == 0)
- alt = pc_pointer(alt);
+ read_u32(child, base, &alt);
}
break;
@@ -305,8 +304,7 @@ get_branch_address(struct task_struct *child, unsigned long pc, unsigned long in
base = ptrace_getrn(child, insn);
- if (read_u32(child, base + nr_regs, &alt) == 0)
- alt = pc_pointer(alt);
+ read_u32(child, base + nr_regs, &alt);
break;
}
break;
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index b7b0720bc1b..1f1eecca7f5 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -26,16 +26,19 @@
#include <linux/fs.h>
#include <asm/cpu.h>
+#include <asm/cputype.h>
#include <asm/elf.h>
#include <asm/procinfo.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
#include <asm/cacheflush.h>
+#include <asm/cachetype.h>
#include <asm/tlbflush.h>
#include <asm/mach/arch.h>
#include <asm/mach/irq.h>
#include <asm/mach/time.h>
+#include <asm/traps.h>
#include "compat.h"
#include "atags.h"
@@ -58,13 +61,14 @@ __setup("fpe=", fpe_setup);
extern void paging_init(struct meminfo *, struct machine_desc *desc);
extern void reboot_setup(char *str);
-extern int root_mountflags;
-extern void _stext, _text, _etext, __data_start, _edata, _end;
+extern void _text, _etext, __data_start, _edata, _end;
unsigned int processor_id;
EXPORT_SYMBOL(processor_id);
unsigned int __machine_arch_type;
EXPORT_SYMBOL(__machine_arch_type);
+unsigned int cacheid;
+EXPORT_SYMBOL(cacheid);
unsigned int __atags_pointer __initdata;
@@ -108,9 +112,6 @@ static struct stack stacks[NR_CPUS];
char elf_platform[ELF_PLATFORM_SIZE];
EXPORT_SYMBOL(elf_platform);
-unsigned long phys_initrd_start __initdata = 0;
-unsigned long phys_initrd_size __initdata = 0;
-
static struct meminfo meminfo __initdata = { 0, };
static const char *cpu_name;
static const char *machine_name;
@@ -175,63 +176,6 @@ static struct resource io_res[] = {
#define lp1 io_res[1]
#define lp2 io_res[2]
-static const char *cache_types[16] = {
- "write-through",
- "write-back",
- "write-back",
- "undefined 3",
- "undefined 4",
- "undefined 5",
- "write-back",
- "write-back",
- "undefined 8",
- "undefined 9",
- "undefined 10",
- "undefined 11",
- "undefined 12",
- "undefined 13",
- "write-back",
- "undefined 15",
-};
-
-static const char *cache_clean[16] = {
- "not required",
- "read-block",
- "cp15 c7 ops",
- "undefined 3",
- "undefined 4",
- "undefined 5",
- "cp15 c7 ops",
- "cp15 c7 ops",
- "undefined 8",
- "undefined 9",
- "undefined 10",
- "undefined 11",
- "undefined 12",
- "undefined 13",
- "cp15 c7 ops",
- "undefined 15",
-};
-
-static const char *cache_lockdown[16] = {
- "not supported",
- "not supported",
- "not supported",
- "undefined 3",
- "undefined 4",
- "undefined 5",
- "format A",
- "format B",
- "undefined 8",
- "undefined 9",
- "undefined 10",
- "undefined 11",
- "undefined 12",
- "undefined 13",
- "format C",
- "undefined 15",
-};
-
static const char *proc_arch[] = {
"undefined/unknown",
"3",
@@ -252,61 +196,19 @@ static const char *proc_arch[] = {
"?(17)",
};
-#define CACHE_TYPE(x) (((x) >> 25) & 15)
-#define CACHE_S(x) ((x) & (1 << 24))
-#define CACHE_DSIZE(x) (((x) >> 12) & 4095) /* only if S=1 */
-#define CACHE_ISIZE(x) ((x) & 4095)
-
-#define CACHE_SIZE(y) (((y) >> 6) & 7)
-#define CACHE_ASSOC(y) (((y) >> 3) & 7)
-#define CACHE_M(y) ((y) & (1 << 2))
-#define CACHE_LINE(y) ((y) & 3)
-
-static inline void dump_cache(const char *prefix, int cpu, unsigned int cache)
-{
- unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0);
-
- printk("CPU%u: %s: %d bytes, associativity %d, %d byte lines, %d sets\n",
- cpu, prefix,
- mult << (8 + CACHE_SIZE(cache)),
- (mult << CACHE_ASSOC(cache)) >> 1,
- 8 << CACHE_LINE(cache),
- 1 << (6 + CACHE_SIZE(cache) - CACHE_ASSOC(cache) -
- CACHE_LINE(cache)));
-}
-
-static void __init dump_cpu_info(int cpu)
-{
- unsigned int info = read_cpuid(CPUID_CACHETYPE);
-
- if (info != processor_id) {
- printk("CPU%u: D %s %s cache\n", cpu, cache_is_vivt() ? "VIVT" : "VIPT",
- cache_types[CACHE_TYPE(info)]);
- if (CACHE_S(info)) {
- dump_cache("I cache", cpu, CACHE_ISIZE(info));
- dump_cache("D cache", cpu, CACHE_DSIZE(info));
- } else {
- dump_cache("cache", cpu, CACHE_ISIZE(info));
- }
- }
-
- if (arch_is_coherent())
- printk("Cache coherency enabled\n");
-}
-
int cpu_architecture(void)
{
int cpu_arch;
- if ((processor_id & 0x0008f000) == 0) {
+ if ((read_cpuid_id() & 0x0008f000) == 0) {
cpu_arch = CPU_ARCH_UNKNOWN;
- } else if ((processor_id & 0x0008f000) == 0x00007000) {
- cpu_arch = (processor_id & (1 << 23)) ? CPU_ARCH_ARMv4T : CPU_ARCH_ARMv3;
- } else if ((processor_id & 0x00080000) == 0x00000000) {
- cpu_arch = (processor_id >> 16) & 7;
+ } else if ((read_cpuid_id() & 0x0008f000) == 0x00007000) {
+ cpu_arch = (read_cpuid_id() & (1 << 23)) ? CPU_ARCH_ARMv4T : CPU_ARCH_ARMv3;
+ } else if ((read_cpuid_id() & 0x00080000) == 0x00000000) {
+ cpu_arch = (read_cpuid_id() >> 16) & 7;
if (cpu_arch)
cpu_arch += CPU_ARCH_ARMv3;
- } else if ((processor_id & 0x000f0000) == 0x000f0000) {
+ } else if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) {
unsigned int mmfr0;
/* Revised CPUID format. Read the Memory Model Feature
@@ -327,6 +229,34 @@ int cpu_architecture(void)
return cpu_arch;
}
+static void __init cacheid_init(void)
+{
+ unsigned int cachetype = read_cpuid_cachetype();
+ unsigned int arch = cpu_architecture();
+
+ if (arch >= CPU_ARCH_ARMv7) {
+ cacheid = CACHEID_VIPT_NONALIASING;
+ if ((cachetype & (3 << 14)) == 1 << 14)
+ cacheid |= CACHEID_ASID_TAGGED;
+ } else if (arch >= CPU_ARCH_ARMv6) {
+ if (cachetype & (1 << 23))
+ cacheid = CACHEID_VIPT_ALIASING;
+ else
+ cacheid = CACHEID_VIPT_NONALIASING;
+ } else {
+ cacheid = CACHEID_VIVT;
+ }
+
+ printk("CPU: %s data cache, %s instruction cache\n",
+ cache_is_vivt() ? "VIVT" :
+ cache_is_vipt_aliasing() ? "VIPT aliasing" :
+ cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown",
+ cache_is_vivt() ? "VIVT" :
+ icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" :
+ cache_is_vipt_aliasing() ? "VIPT aliasing" :
+ cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown");
+}
+
/*
* These functions re-use the assembly code in head.S, which
* already provide the required functionality.
@@ -343,10 +273,10 @@ static void __init setup_processor(void)
* types. The linker builds this table for us from the
* entries in arch/arm/mm/proc-*.S
*/
- list = lookup_processor_type(processor_id);
+ list = lookup_processor_type(read_cpuid_id());
if (!list) {
printk("CPU configuration botched (ID %08x), unable "
- "to continue.\n", processor_id);
+ "to continue.\n", read_cpuid_id());
while (1);
}
@@ -366,7 +296,7 @@ static void __init setup_processor(void)
#endif
printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
- cpu_name, processor_id, (int)processor_id & 15,
+ cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
proc_arch[cpu_architecture()], cr_alignment);
sprintf(init_utsname()->machine, "%s%c", list->arch_name, ENDIANNESS);
@@ -376,14 +306,14 @@ static void __init setup_processor(void)
elf_hwcap &= ~HWCAP_THUMB;
#endif
+ cacheid_init();
cpu_proc_init();
}
/*
* cpu_init - initialise one CPU.
*
- * cpu_init dumps the cache information, initialises SMP specific
- * information, and sets up the per-CPU stacks.
+ * cpu_init sets up the per-CPU stacks.
*/
void cpu_init(void)
{
@@ -395,9 +325,6 @@ void cpu_init(void)
BUG();
}
- if (system_state == SYSTEM_BOOTING)
- dump_cpu_info(cpu);
-
/*
* setup stacks for re-entrant exception handlers
*/
@@ -440,20 +367,6 @@ static struct machine_desc * __init setup_machine(unsigned int nr)
return list;
}
-static void __init early_initrd(char **p)
-{
- unsigned long start, size;
-
- start = memparse(*p, p);
- if (**p == ',') {
- size = memparse((*p) + 1, p);
-
- phys_initrd_start = start;
- phys_initrd_size = size;
- }
-}
-__early_param("initrd=", early_initrd);
-
static void __init arm_add_memory(unsigned long start, unsigned long size)
{
struct membank *bank;
@@ -513,12 +426,12 @@ static void __init parse_cmdline(char **cmdline_p, char *from)
struct early_params *p;
for (p = &__early_begin; p < &__early_end; p++) {
- int len = strlen(p->arg);
+ int arglen = strlen(p->arg);
- if (memcmp(from, p->arg, len) == 0) {
+ if (memcmp(from, p->arg, arglen) == 0) {
if (to != command_line)
to -= 1;
- from += len;
+ from += arglen;
p->fn(&from);
while (*from != ' ' && *from != '\0')
@@ -565,18 +478,13 @@ request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
kernel_data.end = virt_to_phys(&_end - 1);
for (i = 0; i < mi->nr_banks; i++) {
- unsigned long virt_start, virt_end;
-
if (mi->bank[i].size == 0)
continue;
- virt_start = __phys_to_virt(mi->bank[i].start);
- virt_end = virt_start + mi->bank[i].size - 1;
-
res = alloc_bootmem_low(sizeof(*res));
res->name = "System RAM";
- res->start = __virt_to_phys(virt_start);
- res->end = __virt_to_phys(virt_end);
+ res->start = mi->bank[i].start;
+ res->end = mi->bank[i].start + mi->bank[i].size - 1;
res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
request_resource(&iomem_resource, res);
@@ -680,26 +588,6 @@ static int __init parse_tag_ramdisk(const struct tag *tag)
__tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
-static int __init parse_tag_initrd(const struct tag *tag)
-{
- printk(KERN_WARNING "ATAG_INITRD is deprecated; "
- "please update your bootloader.\n");
- phys_initrd_start = __virt_to_phys(tag->u.initrd.start);
- phys_initrd_size = tag->u.initrd.size;
- return 0;
-}
-
-__tagtable(ATAG_INITRD, parse_tag_initrd);
-
-static int __init parse_tag_initrd2(const struct tag *tag)
-{
- phys_initrd_start = tag->u.initrd.start;
- phys_initrd_size = tag->u.initrd.size;
- return 0;
-}
-
-__tagtable(ATAG_INITRD2, parse_tag_initrd2);
-
static int __init parse_tag_serialnr(const struct tag *tag)
{
system_serial_low = tag->u.serialnr.low;
@@ -853,6 +741,7 @@ void __init setup_arch(char **cmdline_p)
conswitchp = &dummy_con;
#endif
#endif
+ early_trap_init();
}
@@ -886,28 +775,12 @@ static const char *hwcap_str[] = {
NULL
};
-static void
-c_show_cache(struct seq_file *m, const char *type, unsigned int cache)
-{
- unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0);
-
- seq_printf(m, "%s size\t\t: %d\n"
- "%s assoc\t\t: %d\n"
- "%s line length\t: %d\n"
- "%s sets\t\t: %d\n",
- type, mult << (8 + CACHE_SIZE(cache)),
- type, (mult << CACHE_ASSOC(cache)) >> 1,
- type, 8 << CACHE_LINE(cache),
- type, 1 << (6 + CACHE_SIZE(cache) - CACHE_ASSOC(cache) -
- CACHE_LINE(cache)));
-}
-
static int c_show(struct seq_file *m, void *v)
{
int i;
seq_printf(m, "Processor\t: %s rev %d (%s)\n",
- cpu_name, (int)processor_id & 15, elf_platform);
+ cpu_name, read_cpuid_id() & 15, elf_platform);
#if defined(CONFIG_SMP)
for_each_online_cpu(i) {
@@ -934,47 +807,26 @@ static int c_show(struct seq_file *m, void *v)
if (elf_hwcap & (1 << i))
seq_printf(m, "%s ", hwcap_str[i]);
- seq_printf(m, "\nCPU implementer\t: 0x%02x\n", processor_id >> 24);
+ seq_printf(m, "\nCPU implementer\t: 0x%02x\n", read_cpuid_id() >> 24);
seq_printf(m, "CPU architecture: %s\n", proc_arch[cpu_architecture()]);
- if ((processor_id & 0x0008f000) == 0x00000000) {
+ if ((read_cpuid_id() & 0x0008f000) == 0x00000000) {
/* pre-ARM7 */
- seq_printf(m, "CPU part\t: %07x\n", processor_id >> 4);
+ seq_printf(m, "CPU part\t: %07x\n", read_cpuid_id() >> 4);
} else {
- if ((processor_id & 0x0008f000) == 0x00007000) {
+ if ((read_cpuid_id() & 0x0008f000) == 0x00007000) {
/* ARM7 */
seq_printf(m, "CPU variant\t: 0x%02x\n",
- (processor_id >> 16) & 127);
+ (read_cpuid_id() >> 16) & 127);
} else {
/* post-ARM7 */
seq_printf(m, "CPU variant\t: 0x%x\n",
- (processor_id >> 20) & 15);
+ (read_cpuid_id() >> 20) & 15);
}
seq_printf(m, "CPU part\t: 0x%03x\n",
- (processor_id >> 4) & 0xfff);
- }
- seq_printf(m, "CPU revision\t: %d\n", processor_id & 15);
-
- {
- unsigned int cache_info = read_cpuid(CPUID_CACHETYPE);
- if (cache_info != processor_id) {
- seq_printf(m, "Cache type\t: %s\n"
- "Cache clean\t: %s\n"
- "Cache lockdown\t: %s\n"
- "Cache format\t: %s\n",
- cache_types[CACHE_TYPE(cache_info)],
- cache_clean[CACHE_TYPE(cache_info)],
- cache_lockdown[CACHE_TYPE(cache_info)],
- CACHE_S(cache_info) ? "Harvard" : "Unified");
-
- if (CACHE_S(cache_info)) {
- c_show_cache(m, "I", CACHE_ISIZE(cache_info));
- c_show_cache(m, "D", CACHE_DSIZE(cache_info));
- } else {
- c_show_cache(m, "Cache", CACHE_ISIZE(cache_info));
- }
- }
+ (read_cpuid_id() >> 4) & 0xfff);
}
+ seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15);
seq_puts(m, "\n");
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index ef2f86a5e78..80b8b5c7e07 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -11,11 +11,11 @@
#include <linux/signal.h>
#include <linux/personality.h>
#include <linux/freezer.h>
+#include <linux/uaccess.h>
#include <asm/elf.h>
#include <asm/cacheflush.h>
#include <asm/ucontext.h>
-#include <asm/uaccess.h>
#include <asm/unistd.h>
#include "ptrace.h"
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index eefae1de334..e42a749a56d 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -68,20 +68,10 @@ enum ipi_msg_type {
IPI_TIMER,
IPI_RESCHEDULE,
IPI_CALL_FUNC,
+ IPI_CALL_FUNC_SINGLE,
IPI_CPU_STOP,
};
-struct smp_call_struct {
- void (*func)(void *info);
- void *info;
- int wait;
- cpumask_t pending;
- cpumask_t unfinished;
-};
-
-static struct smp_call_struct * volatile smp_call_function_data;
-static DEFINE_SPINLOCK(smp_call_function_lock);
-
int __cpuinit __cpu_up(unsigned int cpu)
{
struct cpuinfo_arm *ci = &per_cpu(cpu_data, cpu);
@@ -110,7 +100,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
* a 1:1 mapping for the physical address of the kernel.
*/
pgd = pgd_alloc(&init_mm);
- pmd = pmd_offset(pgd, PHYS_OFFSET);
+ pmd = pmd_offset(pgd + pgd_index(PHYS_OFFSET), PHYS_OFFSET);
*pmd = __pmd((PHYS_OFFSET & PGDIR_MASK) |
PMD_TYPE_SECT | PMD_SECT_AP_WRITE);
@@ -149,7 +139,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
secondary_data.stack = NULL;
secondary_data.pgdir = 0;
- *pmd_offset(pgd, PHYS_OFFSET) = __pmd(0);
+ *pmd = __pmd(0);
pgd_free(&init_mm, pgd);
if (ret) {
@@ -287,6 +277,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
/*
* Enable local interrupts.
*/
+ notify_cpu_starting(cpu);
local_irq_enable();
local_fiq_enable();
@@ -366,114 +357,15 @@ static void send_ipi_message(cpumask_t callmap, enum ipi_msg_type msg)
local_irq_restore(flags);
}
-/*
- * You must not call this function with disabled interrupts, from a
- * hardware interrupt handler, nor from a bottom half handler.
- */
-static int smp_call_function_on_cpu(void (*func)(void *info), void *info,
- int retry, int wait, cpumask_t callmap)
-{
- struct smp_call_struct data;
- unsigned long timeout;
- int ret = 0;
-
- data.func = func;
- data.info = info;
- data.wait = wait;
-
- cpu_clear(smp_processor_id(), callmap);
- if (cpus_empty(callmap))
- goto out;
-
- data.pending = callmap;
- if (wait)
- data.unfinished = callmap;
-
- /*
- * try to get the mutex on smp_call_function_data
- */
- spin_lock(&smp_call_function_lock);
- smp_call_function_data = &data;
-
- send_ipi_message(callmap, IPI_CALL_FUNC);
-
- timeout = jiffies + HZ;
- while (!cpus_empty(data.pending) && time_before(jiffies, timeout))
- barrier();
-
- /*
- * did we time out?
- */
- if (!cpus_empty(data.pending)) {
- /*
- * this may be causing our panic - report it
- */
- printk(KERN_CRIT
- "CPU%u: smp_call_function timeout for %p(%p)\n"
- " callmap %lx pending %lx, %swait\n",
- smp_processor_id(), func, info, *cpus_addr(callmap),
- *cpus_addr(data.pending), wait ? "" : "no ");
-
- /*
- * TRACE
- */
- timeout = jiffies + (5 * HZ);
- while (!cpus_empty(data.pending) && time_before(jiffies, timeout))
- barrier();
-
- if (cpus_empty(data.pending))
- printk(KERN_CRIT " RESOLVED\n");
- else
- printk(KERN_CRIT " STILL STUCK\n");
- }
-
- /*
- * whatever happened, we're done with the data, so release it
- */
- smp_call_function_data = NULL;
- spin_unlock(&smp_call_function_lock);
-
- if (!cpus_empty(data.pending)) {
- ret = -ETIMEDOUT;
- goto out;
- }
-
- if (wait)
- while (!cpus_empty(data.unfinished))
- barrier();
- out:
-
- return 0;
-}
-
-int smp_call_function(void (*func)(void *info), void *info, int retry,
- int wait)
+void arch_send_call_function_ipi(cpumask_t mask)
{
- return smp_call_function_on_cpu(func, info, retry, wait,
- cpu_online_map);
+ send_ipi_message(mask, IPI_CALL_FUNC);
}
-EXPORT_SYMBOL_GPL(smp_call_function);
-int smp_call_function_single(int cpu, void (*func)(void *info), void *info,
- int retry, int wait)
+void arch_send_call_function_single_ipi(int cpu)
{
- /* prevent preemption and reschedule on another processor */
- int current_cpu = get_cpu();
- int ret = 0;
-
- if (cpu == current_cpu) {
- local_irq_disable();
- func(info);
- local_irq_enable();
- } else
- ret = smp_call_function_on_cpu(func, info, retry, wait,
- cpumask_of_cpu(cpu));
-
- put_cpu();
-
- return ret;
+ send_ipi_message(cpumask_of_cpu(cpu), IPI_CALL_FUNC_SINGLE);
}
-EXPORT_SYMBOL_GPL(smp_call_function_single);
void show_ipi_list(struct seq_file *p)
{
@@ -521,27 +413,6 @@ asmlinkage void __exception do_local_timer(struct pt_regs *regs)
}
#endif
-/*
- * ipi_call_function - handle IPI from smp_call_function()
- *
- * Note that we copy data out of the cross-call structure and then
- * let the caller know that we're here and have done with their data
- */
-static void ipi_call_function(unsigned int cpu)
-{
- struct smp_call_struct *data = smp_call_function_data;
- void (*func)(void *info) = data->func;
- void *info = data->info;
- int wait = data->wait;
-
- cpu_clear(cpu, data->pending);
-
- func(info);
-
- if (wait)
- cpu_clear(cpu, data->unfinished);
-}
-
static DEFINE_SPINLOCK(stop_lock);
/*
@@ -611,7 +482,11 @@ asmlinkage void __exception do_IPI(struct pt_regs *regs)
break;
case IPI_CALL_FUNC:
- ipi_call_function(cpu);
+ generic_smp_call_function_interrupt();
+ break;
+
+ case IPI_CALL_FUNC_SINGLE:
+ generic_smp_call_function_single_interrupt();
break;
case IPI_CPU_STOP:
@@ -662,14 +537,13 @@ int setup_profiling_timer(unsigned int multiplier)
}
static int
-on_each_cpu_mask(void (*func)(void *), void *info, int retry, int wait,
- cpumask_t mask)
+on_each_cpu_mask(void (*func)(void *), void *info, int wait, cpumask_t mask)
{
int ret = 0;
preempt_disable();
- ret = smp_call_function_on_cpu(func, info, retry, wait, mask);
+ ret = smp_call_function_mask(mask, func, info, wait);
if (cpu_isset(smp_processor_id(), mask))
func(info);
@@ -731,14 +605,14 @@ static inline void ipi_flush_tlb_kernel_range(void *arg)
void flush_tlb_all(void)
{
- on_each_cpu(ipi_flush_tlb_all, NULL, 1, 1);
+ on_each_cpu(ipi_flush_tlb_all, NULL, 1);
}
void flush_tlb_mm(struct mm_struct *mm)
{
cpumask_t mask = mm->cpu_vm_mask;
- on_each_cpu_mask(ipi_flush_tlb_mm, mm, 1, 1, mask);
+ on_each_cpu_mask(ipi_flush_tlb_mm, mm, 1, mask);
}
void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
@@ -749,7 +623,7 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
ta.ta_vma = vma;
ta.ta_start = uaddr;
- on_each_cpu_mask(ipi_flush_tlb_page, &ta, 1, 1, mask);
+ on_each_cpu_mask(ipi_flush_tlb_page, &ta, 1, mask);
}
void flush_tlb_kernel_page(unsigned long kaddr)
@@ -758,7 +632,7 @@ void flush_tlb_kernel_page(unsigned long kaddr)
ta.ta_start = kaddr;
- on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1, 1);
+ on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1);
}
void flush_tlb_range(struct vm_area_struct *vma,
@@ -771,7 +645,7 @@ void flush_tlb_range(struct vm_area_struct *vma,
ta.ta_start = start;
ta.ta_end = end;
- on_each_cpu_mask(ipi_flush_tlb_range, &ta, 1, 1, mask);
+ on_each_cpu_mask(ipi_flush_tlb_range, &ta, 1, mask);
}
void flush_tlb_kernel_range(unsigned long start, unsigned long end)
@@ -781,5 +655,5 @@ void flush_tlb_kernel_range(unsigned long start, unsigned long end)
ta.ta_start = start;
ta.ta_end = end;
- on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1, 1);
+ on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1);
}
diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c
index ae31deb2d06..fc650f64df4 100644
--- a/arch/arm/kernel/stacktrace.c
+++ b/arch/arm/kernel/stacktrace.c
@@ -36,6 +36,7 @@ EXPORT_SYMBOL(walk_stackframe);
#ifdef CONFIG_STACKTRACE
struct stack_trace_data {
struct stack_trace *trace;
+ unsigned int no_sched_functions;
unsigned int skip;
};
@@ -43,27 +44,53 @@ static int save_trace(struct stackframe *frame, void *d)
{
struct stack_trace_data *data = d;
struct stack_trace *trace = data->trace;
+ unsigned long addr = frame->lr;
+ if (data->no_sched_functions && in_sched_functions(addr))
+ return 0;
if (data->skip) {
data->skip--;
return 0;
}
- trace->entries[trace->nr_entries++] = frame->lr;
+ trace->entries[trace->nr_entries++] = addr;
return trace->nr_entries >= trace->max_entries;
}
-void save_stack_trace(struct stack_trace *trace)
+void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
{
struct stack_trace_data data;
unsigned long fp, base;
data.trace = trace;
data.skip = trace->skip;
- base = (unsigned long)task_stack_page(current);
- asm("mov %0, fp" : "=r" (fp));
+ base = (unsigned long)task_stack_page(tsk);
+
+ if (tsk != current) {
+#ifdef CONFIG_SMP
+ /*
+ * What guarantees do we have here that 'tsk'
+ * is not running on another CPU?
+ */
+ BUG();
+#else
+ data.no_sched_functions = 1;
+ fp = thread_saved_fp(tsk);
+#endif
+ } else {
+ data.no_sched_functions = 0;
+ asm("mov %0, fp" : "=r" (fp));
+ }
walk_stackframe(fp, base, base + THREAD_SIZE, save_trace, &data);
+ if (trace->nr_entries < trace->max_entries)
+ trace->entries[trace->nr_entries++] = ULONG_MAX;
+}
+
+void save_stack_trace(struct stack_trace *trace)
+{
+ save_stack_trace_tsk(current, trace);
}
+EXPORT_SYMBOL_GPL(save_stack_trace);
#endif
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c
index 0128687ba0f..b3ec641b5cf 100644
--- a/arch/arm/kernel/sys_arm.c
+++ b/arch/arm/kernel/sys_arm.c
@@ -27,8 +27,7 @@
#include <linux/file.h>
#include <linux/utsname.h>
#include <linux/ipc.h>
-
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
extern unsigned long do_mremap(unsigned long addr, unsigned long old_len,
unsigned long new_len, unsigned long flags,
diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c
index 96ab5f52949..42623db7f87 100644
--- a/arch/arm/kernel/sys_oabi-compat.c
+++ b/arch/arm/kernel/sys_oabi-compat.c
@@ -82,7 +82,7 @@
#include <linux/socket.h>
#include <linux/net.h>
#include <linux/ipc.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
struct oldabi_stat64 {
unsigned long long st_dev;
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index b5867eca1d0..c68b44aa88d 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -59,7 +59,7 @@ unsigned long profile_pc(struct pt_regs *regs)
if (in_lock_functions(pc)) {
fp = regs->ARM_fp;
- pc = pc_pointer(((unsigned long *)fp)[-1]);
+ pc = ((unsigned long *)fp)[-1];
}
return pc;
@@ -130,7 +130,9 @@ static const struct leds_evt_name evt_names[] = {
{ "red", led_red_on, led_red_off },
};
-static ssize_t leds_store(struct sys_device *dev, const char *buf, size_t size)
+static ssize_t leds_store(struct sys_device *dev,
+ struct sysdev_attribute *attr,
+ const char *buf, size_t size)
{
int ret = -EINVAL, len = strcspn(buf, " ");
@@ -365,108 +367,6 @@ static struct sysdev_class timer_sysclass = {
.resume = timer_resume,
};
-#ifdef CONFIG_NO_IDLE_HZ
-static int timer_dyn_tick_enable(void)
-{
- struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick;
- unsigned long flags;
- int ret = -ENODEV;
-
- if (dyn_tick) {
- spin_lock_irqsave(&dyn_tick->lock, flags);
- ret = 0;
- if (!(dyn_tick->state & DYN_TICK_ENABLED)) {
- ret = dyn_tick->enable();
-
- if (ret == 0)
- dyn_tick->state |= DYN_TICK_ENABLED;
- }
- spin_unlock_irqrestore(&dyn_tick->lock, flags);
- }
-
- return ret;
-}
-
-static int timer_dyn_tick_disable(void)
-{
- struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick;
- unsigned long flags;
- int ret = -ENODEV;
-
- if (dyn_tick) {
- spin_lock_irqsave(&dyn_tick->lock, flags);
- ret = 0;
- if (dyn_tick->state & DYN_TICK_ENABLED) {
- ret = dyn_tick->disable();
-
- if (ret == 0)
- dyn_tick->state &= ~DYN_TICK_ENABLED;
- }
- spin_unlock_irqrestore(&dyn_tick->lock, flags);
- }
-
- return ret;
-}
-
-/*
- * Reprogram the system timer for at least the calculated time interval.
- * This function should be called from the idle thread with IRQs disabled,
- * immediately before sleeping.
- */
-void timer_dyn_reprogram(void)
-{
- struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick;
- unsigned long next, seq, flags;
-
- if (!dyn_tick)
- return;
-
- spin_lock_irqsave(&dyn_tick->lock, flags);
- if (dyn_tick->state & DYN_TICK_ENABLED) {
- next = next_timer_interrupt();
- do {
- seq = read_seqbegin(&xtime_lock);
- dyn_tick->reprogram(next - jiffies);
- } while (read_seqretry(&xtime_lock, seq));
- }
- spin_unlock_irqrestore(&dyn_tick->lock, flags);
-}
-
-static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf)
-{
- return sprintf(buf, "%i\n",
- (system_timer->dyn_tick->state & DYN_TICK_ENABLED) >> 1);
-}
-
-static ssize_t timer_set_dyn_tick(struct sys_device *dev, const char *buf,
- size_t count)
-{
- unsigned int enable = simple_strtoul(buf, NULL, 2);
-
- if (enable)
- timer_dyn_tick_enable();
- else
- timer_dyn_tick_disable();
-
- return count;
-}
-static SYSDEV_ATTR(dyn_tick, 0644, timer_show_dyn_tick, timer_set_dyn_tick);
-
-/*
- * dyntick=enable|disable
- */
-static char dyntick_str[4] __initdata = "";
-
-static int __init dyntick_setup(char *str)
-{
- if (str)
- strlcpy(dyntick_str, str, sizeof(dyntick_str));
- return 1;
-}
-
-__setup("dyntick=", dyntick_setup);
-#endif
-
static int __init timer_init_sysfs(void)
{
int ret = sysdev_class_register(&timer_sysclass);
@@ -475,19 +375,6 @@ static int __init timer_init_sysfs(void)
ret = sysdev_register(&system_timer->dev);
}
-#ifdef CONFIG_NO_IDLE_HZ
- if (ret == 0 && system_timer->dyn_tick) {
- ret = sysdev_create_file(&system_timer->dev, &attr_dyn_tick);
-
- /*
- * Turn on dynamic tick after calibrate delay
- * for correct bogomips
- */
- if (ret == 0 && dyntick_str[0] == 'e')
- ret = timer_dyn_tick_enable();
- }
-#endif
-
return ret;
}
@@ -500,10 +387,5 @@ void __init time_init(void)
system_timer->offset = dummy_gettimeoffset;
#endif
system_timer->init();
-
-#ifdef CONFIG_NO_IDLE_HZ
- if (system_timer->dyn_tick)
- spin_lock_init(&system_timer->dyn_tick->lock);
-#endif
}
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 5595fdd75e8..57e6874d0b8 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -19,15 +19,13 @@
#include <linux/kallsyms.h>
#include <linux/delay.h>
#include <linux/init.h>
-#include <linux/kprobes.h>
+#include <linux/uaccess.h>
#include <asm/atomic.h>
#include <asm/cacheflush.h>
#include <asm/system.h>
-#include <asm/uaccess.h>
#include <asm/unistd.h>
#include <asm/traps.h>
-#include <asm/io.h>
#include "ptrace.h"
#include "signal.h"
@@ -69,7 +67,8 @@ void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long
*/
static int verify_stack(unsigned long sp)
{
- if (sp < PAGE_OFFSET || (sp > (unsigned long)high_memory && high_memory != 0))
+ if (sp < PAGE_OFFSET ||
+ (sp > (unsigned long)high_memory && high_memory != NULL))
return -EFAULT;
return 0;
@@ -288,14 +287,28 @@ void unregister_undef_hook(struct undef_hook *hook)
spin_unlock_irqrestore(&undef_lock, flags);
}
+static int call_undef_hook(struct pt_regs *regs, unsigned int instr)
+{
+ struct undef_hook *hook;
+ unsigned long flags;
+ int (*fn)(struct pt_regs *regs, unsigned int instr) = NULL;
+
+ spin_lock_irqsave(&undef_lock, flags);
+ list_for_each_entry(hook, &undef_hook, node)
+ if ((instr & hook->instr_mask) == hook->instr_val &&
+ (regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val)
+ fn = hook->fn;
+ spin_unlock_irqrestore(&undef_lock, flags);
+
+ return fn ? fn(regs, instr) : 1;
+}
+
asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
{
unsigned int correction = thumb_mode(regs) ? 2 : 4;
unsigned int instr;
- struct undef_hook *hook;
siginfo_t info;
void __user *pc;
- unsigned long flags;
/*
* According to the ARM ARM, PC is 2 or 4 bytes ahead,
@@ -314,28 +327,8 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
get_user(instr, (u32 __user *)pc);
}
-#ifdef CONFIG_KPROBES
- /*
- * It is possible to have recursive kprobes, so we can't call
- * the kprobe trap handler with the undef_lock held.
- */
- if (instr == KPROBE_BREAKPOINT_INSTRUCTION && !user_mode(regs)) {
- kprobe_trap_handler(regs, instr);
+ if (call_undef_hook(regs, instr) == 0)
return;
- }
-#endif
-
- spin_lock_irqsave(&undef_lock, flags);
- list_for_each_entry(hook, &undef_hook, node) {
- if ((instr & hook->instr_mask) == hook->instr_val &&
- (regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val) {
- if (hook->fn(regs, instr) == 0) {
- spin_unlock_irqrestore(&undef_lock, flags);
- return;
- }
- }
- }
- spin_unlock_irqrestore(&undef_lock, flags);
#ifdef CONFIG_DEBUG_USER
if (user_debug & UDBG_UNDEFINED) {
@@ -708,6 +701,11 @@ EXPORT_SYMBOL(abort);
void __init trap_init(void)
{
+ return;
+}
+
+void __init early_trap_init(void)
+{
unsigned long vectors = CONFIG_VECTORS_BASE;
extern char __stubs_start[], __stubs_end[];
extern char __vectors_start[], __vectors_end[];
diff --git a/arch/arm/kernel/xscale-cp0.c b/arch/arm/kernel/xscale-cp0.c
index 180000bfdc8..17127db906f 100644
--- a/arch/arm/kernel/xscale-cp0.c
+++ b/arch/arm/kernel/xscale-cp0.c
@@ -14,8 +14,8 @@
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/init.h>
+#include <linux/io.h>
#include <asm/thread_notify.h>
-#include <asm/io.h>
static inline void dsp_save_state(u32 *state)
{