aboutsummaryrefslogtreecommitdiffstats
path: root/arch/avr32/kernel
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-10-03 19:28:46 +0200
committerIngo Molnar <mingo@elte.hu>2008-10-03 19:28:46 +0200
commitf68ec0c24755e5cdb779be6240925f2175311d84 (patch)
treea7b7128e61a8456385d82bd1c7ca5f14eecbf2ca /arch/avr32/kernel
parent98920dc3d1113b883cbc73e3293446d3525c6042 (diff)
parent94aca1dac6f6d21f4b07e4864baf7768cabcc6e7 (diff)
downloadlinux-f68ec0c24755e5cdb779be6240925f2175311d84.tar.gz
Merge commit 'v2.6.27-rc8' into x86/setup
Diffstat (limited to 'arch/avr32/kernel')
-rw-r--r--arch/avr32/kernel/.gitignore1
-rw-r--r--arch/avr32/kernel/asm-offsets.c6
-rw-r--r--arch/avr32/kernel/avr32_ksyms.c1
-rw-r--r--arch/avr32/kernel/cpu.c38
-rw-r--r--arch/avr32/kernel/entry-avr32b.S59
-rw-r--r--arch/avr32/kernel/process.c4
-rw-r--r--arch/avr32/kernel/setup.c4
-rw-r--r--arch/avr32/kernel/stacktrace.c1
-rw-r--r--arch/avr32/kernel/syscall-stubs.S9
-rw-r--r--arch/avr32/kernel/syscall_table.S2
-rw-r--r--arch/avr32/kernel/time.c8
-rw-r--r--arch/avr32/kernel/traps.c8
12 files changed, 115 insertions, 26 deletions
diff --git a/arch/avr32/kernel/.gitignore b/arch/avr32/kernel/.gitignore
new file mode 100644
index 000000000000..c5f676c3c224
--- /dev/null
+++ b/arch/avr32/kernel/.gitignore
@@ -0,0 +1 @@
+vmlinux.lds
diff --git a/arch/avr32/kernel/asm-offsets.c b/arch/avr32/kernel/asm-offsets.c
index e4796c67a831..d6a8193a1d2f 100644
--- a/arch/avr32/kernel/asm-offsets.c
+++ b/arch/avr32/kernel/asm-offsets.c
@@ -4,6 +4,8 @@
* to extract and format the required data.
*/
+#include <linux/mm.h>
+#include <linux/sched.h>
#include <linux/thread_info.h>
#include <linux/kbuild.h>
@@ -17,4 +19,8 @@ void foo(void)
OFFSET(TI_rar_saved, thread_info, rar_saved);
OFFSET(TI_rsr_saved, thread_info, rsr_saved);
OFFSET(TI_restart_block, thread_info, restart_block);
+ BLANK();
+ OFFSET(TSK_active_mm, task_struct, active_mm);
+ BLANK();
+ OFFSET(MM_pgd, mm_struct, pgd);
}
diff --git a/arch/avr32/kernel/avr32_ksyms.c b/arch/avr32/kernel/avr32_ksyms.c
index 84a7d44edc67..11e310c567a9 100644
--- a/arch/avr32/kernel/avr32_ksyms.c
+++ b/arch/avr32/kernel/avr32_ksyms.c
@@ -58,6 +58,7 @@ EXPORT_SYMBOL(find_first_zero_bit);
EXPORT_SYMBOL(find_next_zero_bit);
EXPORT_SYMBOL(find_first_bit);
EXPORT_SYMBOL(find_next_bit);
+EXPORT_SYMBOL(generic_find_next_le_bit);
EXPORT_SYMBOL(generic_find_next_zero_le_bit);
/* I/O primitives (lib/io-*.S) */
diff --git a/arch/avr32/kernel/cpu.c b/arch/avr32/kernel/cpu.c
index b8409caeb23d..e84faffbbeca 100644
--- a/arch/avr32/kernel/cpu.c
+++ b/arch/avr32/kernel/cpu.c
@@ -26,14 +26,16 @@ static DEFINE_PER_CPU(struct cpu, cpu_devices);
* XXX: If/when a SMP-capable implementation of AVR32 will ever be
* made, we must make sure that the code executes on the correct CPU.
*/
-static ssize_t show_pc0event(struct sys_device *dev, char *buf)
+static ssize_t show_pc0event(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
unsigned long pccr;
pccr = sysreg_read(PCCR);
return sprintf(buf, "0x%lx\n", (pccr >> 12) & 0x3f);
}
-static ssize_t store_pc0event(struct sys_device *dev, const char *buf,
+static ssize_t store_pc0event(struct sys_device *dev,
+ struct sysdev_attribute *attr, const char *buf,
size_t count)
{
unsigned long val;
@@ -46,15 +48,17 @@ static ssize_t store_pc0event(struct sys_device *dev, const char *buf,
sysreg_write(PCCR, val);
return count;
}
-static ssize_t show_pc0count(struct sys_device *dev, char *buf)
+static ssize_t show_pc0count(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
unsigned long pcnt0;
pcnt0 = sysreg_read(PCNT0);
return sprintf(buf, "%lu\n", pcnt0);
}
-static ssize_t store_pc0count(struct sys_device *dev, const char *buf,
- size_t count)
+static ssize_t store_pc0count(struct sys_device *dev,
+ struct sysdev_attribute *attr,
+ const char *buf, size_t count)
{
unsigned long val;
char *endp;
@@ -67,14 +71,16 @@ static ssize_t store_pc0count(struct sys_device *dev, const char *buf,
return count;
}
-static ssize_t show_pc1event(struct sys_device *dev, char *buf)
+static ssize_t show_pc1event(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
unsigned long pccr;
pccr = sysreg_read(PCCR);
return sprintf(buf, "0x%lx\n", (pccr >> 18) & 0x3f);
}
-static ssize_t store_pc1event(struct sys_device *dev, const char *buf,
+static ssize_t store_pc1event(struct sys_device *dev,
+ struct sysdev_attribute *attr, const char *buf,
size_t count)
{
unsigned long val;
@@ -87,14 +93,16 @@ static ssize_t store_pc1event(struct sys_device *dev, const char *buf,
sysreg_write(PCCR, val);
return count;
}
-static ssize_t show_pc1count(struct sys_device *dev, char *buf)
+static ssize_t show_pc1count(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
unsigned long pcnt1;
pcnt1 = sysreg_read(PCNT1);
return sprintf(buf, "%lu\n", pcnt1);
}
-static ssize_t store_pc1count(struct sys_device *dev, const char *buf,
+static ssize_t store_pc1count(struct sys_device *dev,
+ struct sysdev_attribute *attr, const char *buf,
size_t count)
{
unsigned long val;
@@ -108,14 +116,16 @@ static ssize_t store_pc1count(struct sys_device *dev, const char *buf,
return count;
}
-static ssize_t show_pccycles(struct sys_device *dev, char *buf)
+static ssize_t show_pccycles(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
unsigned long pccnt;
pccnt = sysreg_read(PCCNT);
return sprintf(buf, "%lu\n", pccnt);
}
-static ssize_t store_pccycles(struct sys_device *dev, const char *buf,
+static ssize_t store_pccycles(struct sys_device *dev,
+ struct sysdev_attribute *attr, const char *buf,
size_t count)
{
unsigned long val;
@@ -129,14 +139,16 @@ static ssize_t store_pccycles(struct sys_device *dev, const char *buf,
return count;
}
-static ssize_t show_pcenable(struct sys_device *dev, char *buf)
+static ssize_t show_pcenable(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
unsigned long pccr;
pccr = sysreg_read(PCCR);
return sprintf(buf, "%c\n", (pccr & 1)?'1':'0');
}
-static ssize_t store_pcenable(struct sys_device *dev, const char *buf,
+static ssize_t store_pcenable(struct sys_device *dev,
+ struct sysdev_attribute *attr, const char *buf,
size_t count)
{
unsigned long pccr, val;
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S
index 2b398cae110c..33d49377b8be 100644
--- a/arch/avr32/kernel/entry-avr32b.S
+++ b/arch/avr32/kernel/entry-avr32b.S
@@ -334,9 +334,64 @@ save_full_context_ex:
/* Low-level exception handlers */
handle_critical:
+ /*
+ * AT32AP700x errata:
+ *
+ * After a Java stack overflow or underflow trap, any CPU
+ * memory access may cause erratic behavior. This will happen
+ * when the four least significant bits of the JOSP system
+ * register contains any value between 9 and 15 (inclusive).
+ *
+ * Possible workarounds:
+ * - Don't use the Java Extension Module
+ * - Ensure that the stack overflow and underflow trap
+ * handlers do not do any memory access or trigger any
+ * exceptions before the overflow/underflow condition is
+ * cleared (by incrementing or decrementing the JOSP)
+ * - Make sure that JOSP does not contain any problematic
+ * value before doing any exception or interrupt
+ * processing.
+ * - Set up a critical exception handler which writes a
+ * known-to-be-safe value, e.g. 4, to JOSP before doing
+ * any further processing.
+ *
+ * We'll use the last workaround for now since we cannot
+ * guarantee that user space processes don't use Java mode.
+ * Non-well-behaving userland will be terminated with extreme
+ * prejudice.
+ */
+#ifdef CONFIG_CPU_AT32AP700X
+ /*
+ * There's a chance we can't touch memory, so temporarily
+ * borrow PTBR to save the stack pointer while we fix things
+ * up...
+ */
+ mtsr SYSREG_PTBR, sp
+ mov sp, 4
+ mtsr SYSREG_JOSP, sp
+ mfsr sp, SYSREG_PTBR
+ sub pc, -2
+
+ /* Push most of pt_regs on stack. We'll do the rest later */
sub sp, 4
- stmts --sp, r0-lr
- rcall save_full_context_ex
+ pushm r0-r12
+
+ /* PTBR mirrors current_thread_info()->task->active_mm->pgd */
+ get_thread_info r0
+ ld.w r1, r0[TI_task]
+ ld.w r2, r1[TSK_active_mm]
+ ld.w r3, r2[MM_pgd]
+ mtsr SYSREG_PTBR, r3
+#else
+ sub sp, 4
+ pushm r0-r12
+#endif
+ sub r0, sp, -(14 * 4)
+ mov r1, lr
+ mfsr r2, SYSREG_RAR_EX
+ mfsr r3, SYSREG_RSR_EX
+ pushm r0-r3
+
mfsr r12, SYSREG_ECR
mov r11, sp
rcall do_critical_exception
diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c
index 6cf9df176274..2c08ac992ac3 100644
--- a/arch/avr32/kernel/process.c
+++ b/arch/avr32/kernel/process.c
@@ -18,7 +18,7 @@
#include <asm/sysreg.h>
#include <asm/ocd.h>
-#include <asm/arch/pm.h>
+#include <mach/pm.h>
void (*pm_power_off)(void) = NULL;
EXPORT_SYMBOL(pm_power_off);
@@ -31,7 +31,7 @@ void cpu_idle(void)
{
/* endless idle loop with no priority at all */
while (1) {
- tick_nohz_stop_sched_tick();
+ tick_nohz_stop_sched_tick(1);
while (!need_resched())
cpu_idle_sleep();
tick_nohz_restart_sched_tick();
diff --git a/arch/avr32/kernel/setup.c b/arch/avr32/kernel/setup.c
index ce48c14f4349..d8e623c426c1 100644
--- a/arch/avr32/kernel/setup.c
+++ b/arch/avr32/kernel/setup.c
@@ -26,8 +26,8 @@
#include <asm/setup.h>
#include <asm/sysreg.h>
-#include <asm/arch/board.h>
-#include <asm/arch/init.h>
+#include <mach/board.h>
+#include <mach/init.h>
extern int root_mountflags;
diff --git a/arch/avr32/kernel/stacktrace.c b/arch/avr32/kernel/stacktrace.c
index f4bdb448049c..c09f0d8dd679 100644
--- a/arch/avr32/kernel/stacktrace.c
+++ b/arch/avr32/kernel/stacktrace.c
@@ -10,6 +10,7 @@
#include <linux/sched.h>
#include <linux/stacktrace.h>
#include <linux/thread_info.h>
+#include <linux/module.h>
register unsigned long current_frame_pointer asm("r7");
diff --git a/arch/avr32/kernel/syscall-stubs.S b/arch/avr32/kernel/syscall-stubs.S
index 890286a1e62b..673178e235f3 100644
--- a/arch/avr32/kernel/syscall-stubs.S
+++ b/arch/avr32/kernel/syscall-stubs.S
@@ -109,3 +109,12 @@ __sys_epoll_pwait:
rcall sys_epoll_pwait
sub sp, -4
popm pc
+
+ .global __sys_sync_file_range
+ .type __sys_sync_file_range,@function
+__sys_sync_file_range:
+ pushm lr
+ st.w --sp, ARG6
+ rcall sys_sync_file_range
+ sub sp, -4
+ popm pc
diff --git a/arch/avr32/kernel/syscall_table.S b/arch/avr32/kernel/syscall_table.S
index 478bda4c4a09..7ee0057613b3 100644
--- a/arch/avr32/kernel/syscall_table.S
+++ b/arch/avr32/kernel/syscall_table.S
@@ -275,7 +275,7 @@ sys_call_table:
.long sys_set_robust_list
.long sys_get_robust_list /* 260 */
.long __sys_splice
- .long sys_sync_file_range
+ .long __sys_sync_file_range
.long sys_tee
.long sys_vmsplice
.long __sys_epoll_pwait /* 265 */
diff --git a/arch/avr32/kernel/time.c b/arch/avr32/kernel/time.c
index abd954fb7ba0..283481d74a5b 100644
--- a/arch/avr32/kernel/time.c
+++ b/arch/avr32/kernel/time.c
@@ -15,7 +15,7 @@
#include <asm/sysreg.h>
-#include <asm/arch/pm.h>
+#include <mach/pm.h>
static cycle_t read_cycle_count(void)
@@ -43,6 +43,9 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id)
{
struct clock_event_device *evdev = dev_id;
+ if (unlikely(!(intc_get_pending(0) & 1)))
+ return IRQ_NONE;
+
/*
* Disable the interrupt until the clockevent subsystem
* reprograms it.
@@ -55,7 +58,8 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id)
static struct irqaction timer_irqaction = {
.handler = timer_interrupt,
- .flags = IRQF_TIMER | IRQF_DISABLED,
+ /* Oprofile uses the same irq as the timer, so allow it to be shared */
+ .flags = IRQF_TIMER | IRQF_DISABLED | IRQF_SHARED,
.name = "avr32_comparator",
};
diff --git a/arch/avr32/kernel/traps.c b/arch/avr32/kernel/traps.c
index b835c4c01368..0d987373bc01 100644
--- a/arch/avr32/kernel/traps.c
+++ b/arch/avr32/kernel/traps.c
@@ -116,15 +116,15 @@ asmlinkage void do_nmi(unsigned long ecr, struct pt_regs *regs)
switch (ret) {
case NOTIFY_OK:
case NOTIFY_STOP:
- return;
+ break;
case NOTIFY_BAD:
die("Fatal Non-Maskable Interrupt", regs, SIGINT);
default:
+ printk(KERN_ALERT "Got NMI, but nobody cared. Disabling...\n");
+ nmi_disable();
break;
}
-
- printk(KERN_ALERT "Got NMI, but nobody cared. Disabling...\n");
- nmi_disable();
+ nmi_exit();
}
asmlinkage void do_critical_exception(unsigned long ecr, struct pt_regs *regs)