Commit 8f65873e authored by Graf Yang's avatar Graf Yang Committed by Bryan Wu

Blackfin arch: SMP supporting patchset: Blackfin kernel and memory management code

Blackfin dual core BF561 processor can support SMP like features.
https://docs.blackfin.uclinux.org/doku.php?id=linux-kernel:smp-like

In this patch, we provide SMP extend to Blackfin kernel and memory management code
Singed-off-by: default avatarGraf Yang <graf.yang@analog.com>
Signed-off-by: default avatarMike Frysinger <vapier.adi@gmail.com>
Signed-off-by: default avatarBryan Wu <cooloney@kernel.org>
parent b8a98989
......@@ -56,6 +56,9 @@ int main(void)
/* offsets into the thread struct */
DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp));
DEFINE(THREAD_USP, offsetof(struct thread_struct, usp));
DEFINE(THREAD_SR, offsetof(struct thread_struct, seqstat));
DEFINE(PT_SR, offsetof(struct thread_struct, seqstat));
DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0));
DEFINE(THREAD_PC, offsetof(struct thread_struct, pc));
DEFINE(KERNEL_STACK_SIZE, THREAD_SIZE);
......@@ -128,5 +131,31 @@ int main(void)
DEFINE(SIGSEGV, SIGSEGV);
DEFINE(SIGTRAP, SIGTRAP);
/* PDA management (in L1 scratchpad) */
DEFINE(PDA_SYSCFG, offsetof(struct blackfin_pda, syscfg));
#ifdef CONFIG_SMP
DEFINE(PDA_IRQFLAGS, offsetof(struct blackfin_pda, imask));
#endif
DEFINE(PDA_IPDT, offsetof(struct blackfin_pda, ipdt));
DEFINE(PDA_IPDT_SWAPCOUNT, offsetof(struct blackfin_pda, ipdt_swapcount));
DEFINE(PDA_DPDT, offsetof(struct blackfin_pda, dpdt));
DEFINE(PDA_DPDT_SWAPCOUNT, offsetof(struct blackfin_pda, dpdt_swapcount));
DEFINE(PDA_EXIPTR, offsetof(struct blackfin_pda, ex_iptr));
DEFINE(PDA_EXOPTR, offsetof(struct blackfin_pda, ex_optr));
DEFINE(PDA_EXBUF, offsetof(struct blackfin_pda, ex_buf));
DEFINE(PDA_EXIMASK, offsetof(struct blackfin_pda, ex_imask));
DEFINE(PDA_EXSTACK, offsetof(struct blackfin_pda, ex_stack));
#ifdef ANOMALY_05000261
DEFINE(PDA_LFRETX, offsetof(struct blackfin_pda, last_cplb_fault_retx));
#endif
DEFINE(PDA_DCPLB, offsetof(struct blackfin_pda, dcplb_fault_addr));
DEFINE(PDA_ICPLB, offsetof(struct blackfin_pda, icplb_fault_addr));
DEFINE(PDA_RETX, offsetof(struct blackfin_pda, retx));
DEFINE(PDA_SEQSTAT, offsetof(struct blackfin_pda, seqstat));
#ifdef CONFIG_SMP
/* Inter-core lock (in L2 SRAM) */
DEFINE(SIZEOF_CORELOCK, sizeof(struct corelock_slot));
#endif
return 0;
}
......@@ -68,3 +68,37 @@ EXPORT_SYMBOL(insw_8);
EXPORT_SYMBOL(outsl);
EXPORT_SYMBOL(insl);
EXPORT_SYMBOL(insl_16);
#ifdef CONFIG_SMP
EXPORT_SYMBOL(__raw_atomic_update_asm);
EXPORT_SYMBOL(__raw_atomic_clear_asm);
EXPORT_SYMBOL(__raw_atomic_set_asm);
EXPORT_SYMBOL(__raw_atomic_xor_asm);
EXPORT_SYMBOL(__raw_atomic_test_asm);
EXPORT_SYMBOL(__raw_xchg_1_asm);
EXPORT_SYMBOL(__raw_xchg_2_asm);
EXPORT_SYMBOL(__raw_xchg_4_asm);
EXPORT_SYMBOL(__raw_cmpxchg_1_asm);
EXPORT_SYMBOL(__raw_cmpxchg_2_asm);
EXPORT_SYMBOL(__raw_cmpxchg_4_asm);
EXPORT_SYMBOL(__raw_spin_is_locked_asm);
EXPORT_SYMBOL(__raw_spin_lock_asm);
EXPORT_SYMBOL(__raw_spin_trylock_asm);
EXPORT_SYMBOL(__raw_spin_unlock_asm);
EXPORT_SYMBOL(__raw_read_lock_asm);
EXPORT_SYMBOL(__raw_read_trylock_asm);
EXPORT_SYMBOL(__raw_read_unlock_asm);
EXPORT_SYMBOL(__raw_write_lock_asm);
EXPORT_SYMBOL(__raw_write_trylock_asm);
EXPORT_SYMBOL(__raw_write_unlock_asm);
EXPORT_SYMBOL(__raw_bit_set_asm);
EXPORT_SYMBOL(__raw_bit_clear_asm);
EXPORT_SYMBOL(__raw_bit_toggle_asm);
EXPORT_SYMBOL(__raw_bit_test_asm);
EXPORT_SYMBOL(__raw_bit_test_set_asm);
EXPORT_SYMBOL(__raw_bit_test_clear_asm);
EXPORT_SYMBOL(__raw_bit_test_toggle_asm);
EXPORT_SYMBOL(__raw_uncached_fetch_asm);
EXPORT_SYMBOL(__raw_smp_mark_barrier_asm);
EXPORT_SYMBOL(__raw_smp_check_barrier_asm);
#endif
......@@ -30,6 +30,7 @@
#include <linux/linkage.h>
#include <asm/thread_info.h>
#include <asm/errno.h>
#include <asm/blackfin.h>
#include <asm/asm-offsets.h>
#include <asm/context.S>
......
......@@ -36,7 +36,7 @@
#include <linux/irq.h>
#include <asm/trace.h>
static unsigned long irq_err_count;
static atomic_t irq_err_count;
static spinlock_t irq_controller_lock;
/*
......@@ -48,7 +48,7 @@ void dummy_mask_unmask_irq(unsigned int irq)
void ack_bad_irq(unsigned int irq)
{
irq_err_count += 1;
atomic_inc(&irq_err_count);
printk(KERN_ERR "IRQ: spurious interrupt %d\n", irq);
}
EXPORT_SYMBOL(ack_bad_irq);
......@@ -72,7 +72,7 @@ static struct irq_desc bad_irq_desc = {
int show_interrupts(struct seq_file *p, void *v)
{
int i = *(loff_t *) v;
int i = *(loff_t *) v, j;
struct irqaction *action;
unsigned long flags;
......@@ -80,19 +80,20 @@ int show_interrupts(struct seq_file *p, void *v)
spin_lock_irqsave(&irq_desc[i].lock, flags);
action = irq_desc[i].action;
if (!action)
goto unlock;
seq_printf(p, "%3d: %10u ", i, kstat_irqs(i));
goto skip;
seq_printf(p, "%3d: ", i);
for_each_online_cpu(j)
seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
seq_printf(p, " %8s", irq_desc[i].chip->name);
seq_printf(p, " %s", action->name);
for (action = action->next; action; action = action->next)
seq_printf(p, ", %s", action->name);
seq_printf(p, " %s", action->name);
seq_putc(p, '\n');
unlock:
skip:
spin_unlock_irqrestore(&irq_desc[i].lock, flags);
} else if (i == NR_IRQS) {
seq_printf(p, "Err: %10lu\n", irq_err_count);
}
} else if (i == NR_IRQS)
seq_printf(p, "Err: %10u\n", atomic_read(&irq_err_count));
return 0;
}
......@@ -101,7 +102,6 @@ int show_interrupts(struct seq_file *p, void *v)
* come via this function. Instead, they should provide their
* own 'handler'
*/
#ifdef CONFIG_DO_IRQ_L1
__attribute__((l1_text))
#endif
......
......@@ -363,12 +363,12 @@ void kgdb_passive_cpu_callback(void *info)
void kgdb_roundup_cpus(unsigned long flags)
{
smp_call_function(kgdb_passive_cpu_callback, NULL, 0, 0);
smp_call_function(kgdb_passive_cpu_callback, NULL, 0);
}
void kgdb_roundup_cpu(int cpu, unsigned long flags)
{
smp_call_function_single(cpu, kgdb_passive_cpu_callback, NULL, 0, 0);
smp_call_function_single(cpu, kgdb_passive_cpu_callback, NULL, 0);
}
#endif
......
......@@ -343,7 +343,13 @@ apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab,
pr_debug("location is %x, value is %x type is %d \n",
(unsigned int) location32, value,
ELF32_R_TYPE(rel[i].r_info));
#ifdef CONFIG_SMP
if ((unsigned long)location16 >= COREB_L1_DATA_A_START) {
printk(KERN_ERR "module %s: cannot relocate in L1: %u (SMP kernel)",
mod->name, ELF32_R_TYPE(rel[i].r_info));
return -ENOEXEC;
}
#endif
switch (ELF32_R_TYPE(rel[i].r_info)) {
case R_pcrel24:
......@@ -436,6 +442,7 @@ module_finalize(const Elf_Ehdr * hdr,
{
unsigned int i, strindex = 0, symindex = 0;
char *secstrings;
long err = 0;
secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
......@@ -460,8 +467,10 @@ module_finalize(const Elf_Ehdr * hdr,
(strcmp(".rela.l1.text", secstrings + sechdrs[i].sh_name) == 0) ||
((strcmp(".rela.text", secstrings + sechdrs[i].sh_name) == 0) &&
(hdr->e_flags & (EF_BFIN_CODE_IN_L1|EF_BFIN_CODE_IN_L2))))) {
apply_relocate_add((Elf_Shdr *) sechdrs, strtab,
err = apply_relocate_add((Elf_Shdr *) sechdrs, strtab,
symindex, i, mod);
if (err < 0)
return -ENOEXEC;
}
}
return 0;
......
......@@ -171,6 +171,13 @@ asmlinkage int bfin_clone(struct pt_regs *regs)
unsigned long clone_flags;
unsigned long newsp;
#ifdef __ARCH_SYNC_CORE_DCACHE
if (current->rt.nr_cpus_allowed == num_possible_cpus()) {
current->cpus_allowed = cpumask_of_cpu(smp_processor_id());
current->rt.nr_cpus_allowed = 1;
}
#endif
/* syscall2 puts clone_flags in r0 and usp in r1 */
clone_flags = regs->r0;
newsp = regs->r1;
......@@ -338,22 +345,22 @@ int _access_ok(unsigned long addr, unsigned long size)
if (addr >= (unsigned long)__init_begin &&
addr + size <= (unsigned long)__init_end)
return 1;
if (addr >= L1_SCRATCH_START
&& addr + size <= L1_SCRATCH_START + L1_SCRATCH_LENGTH)
if (addr >= get_l1_scratch_start()
&& addr + size <= get_l1_scratch_start() + L1_SCRATCH_LENGTH)
return 1;
#if L1_CODE_LENGTH != 0
if (addr >= L1_CODE_START + (_etext_l1 - _stext_l1)
&& addr + size <= L1_CODE_START + L1_CODE_LENGTH)
if (addr >= get_l1_code_start() + (_etext_l1 - _stext_l1)
&& addr + size <= get_l1_code_start() + L1_CODE_LENGTH)
return 1;
#endif
#if L1_DATA_A_LENGTH != 0
if (addr >= L1_DATA_A_START + (_ebss_l1 - _sdata_l1)
&& addr + size <= L1_DATA_A_START + L1_DATA_A_LENGTH)
if (addr >= get_l1_data_a_start() + (_ebss_l1 - _sdata_l1)
&& addr + size <= get_l1_data_a_start() + L1_DATA_A_LENGTH)
return 1;
#endif
#if L1_DATA_B_LENGTH != 0
if (addr >= L1_DATA_B_START + (_ebss_b_l1 - _sdata_b_l1)
&& addr + size <= L1_DATA_B_START + L1_DATA_B_LENGTH)
if (addr >= get_l1_data_b_start() + (_ebss_b_l1 - _sdata_b_l1)
&& addr + size <= get_l1_data_b_start() + L1_DATA_B_LENGTH)
return 1;
#endif
#if L2_LENGTH != 0
......
......@@ -220,8 +220,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
pr_debug("ptrace: user address is valid\n");
if (L1_CODE_LENGTH != 0 && addr >= L1_CODE_START
&& addr + sizeof(tmp) <= L1_CODE_START + L1_CODE_LENGTH) {
if (L1_CODE_LENGTH != 0 && addr >= get_l1_code_start()
&& addr + sizeof(tmp) <= get_l1_code_start() + L1_CODE_LENGTH) {
safe_dma_memcpy (&tmp, (const void *)(addr), sizeof(tmp));
copied = sizeof(tmp);
......@@ -300,8 +300,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
pr_debug("ptrace: user address is valid\n");
if (L1_CODE_LENGTH != 0 && addr >= L1_CODE_START
&& addr + sizeof(data) <= L1_CODE_START + L1_CODE_LENGTH) {
if (L1_CODE_LENGTH != 0 && addr >= get_l1_code_start()
&& addr + sizeof(data) <= get_l1_code_start() + L1_CODE_LENGTH) {
safe_dma_memcpy ((void *)(addr), &data, sizeof(data));
copied = sizeof(data);
......
......@@ -21,7 +21,7 @@
* the core reset.
*/
__attribute__((l1_text))
static void bfin_reset(void)
static void _bfin_reset(void)
{
/* Wait for completion of "system" events such as cache line
* line fills so that we avoid infinite stalls later on as
......@@ -66,6 +66,18 @@ static void bfin_reset(void)
}
}
static void bfin_reset(void)
{
if (ANOMALY_05000353 || ANOMALY_05000386)
_bfin_reset();
else
/* the bootrom checks to see how it was reset and will
* automatically perform a software reset for us when
* it starts executing boot
*/
asm("raise 1;");
}
__attribute__((weak))
void native_machine_restart(char *cmd)
{
......@@ -75,14 +87,10 @@ void machine_restart(char *cmd)
{
native_machine_restart(cmd);
local_irq_disable();
if (ANOMALY_05000353 || ANOMALY_05000386)
bfin_reset();
if (smp_processor_id())
smp_call_function((void *)bfin_reset, 0, 1);
else
/* the bootrom checks to see how it was reset and will
* automatically perform a software reset for us when
* it starts executing boot
*/
asm("raise 1;");
bfin_reset();
}
__attribute__((weak))
......
This diff is collapsed.
......@@ -34,9 +34,11 @@
#include <linux/interrupt.h>
#include <linux/time.h>
#include <linux/irq.h>
#include <linux/delay.h>
#include <asm/blackfin.h>
#include <asm/time.h>
#include <asm/gptimers.h>
/* This is an NTP setting */
#define TICK_SIZE (tick_nsec / 1000)
......@@ -46,11 +48,14 @@ static unsigned long gettimeoffset(void);
static struct irqaction bfin_timer_irq = {
.name = "BFIN Timer Tick",
#ifdef CONFIG_IRQ_PER_CPU
.flags = IRQF_DISABLED | IRQF_PERCPU,
#else
.flags = IRQF_DISABLED
#endif
};
static void
time_sched_init(irq_handler_t timer_routine)
void setup_core_timer(void)
{
u32 tcount;
......@@ -71,12 +76,41 @@ time_sched_init(irq_handler_t timer_routine)
CSYNC();
bfin_write_TCNTL(7);
}
#ifdef CONFIG_TICK_SOURCE_SYSTMR0
void setup_system_timer0(void)
{
/* Power down the core timer, just to play safe. */
bfin_write_TCNTL(0);
disable_gptimers(TIMER0bit);
set_gptimer_status(0, TIMER_STATUS_TRUN0);
while (get_gptimer_status(0) & TIMER_STATUS_TRUN0)
udelay(10);
set_gptimer_config(0, 0x59); /* IRQ enable, periodic, PWM_OUT, SCLKed, OUT PAD disabled */
set_gptimer_period(TIMER0_id, get_sclk() / HZ);
set_gptimer_pwidth(TIMER0_id, 1);
SSYNC();
enable_gptimers(TIMER0bit);
}
#endif
static void
time_sched_init(irqreturn_t(*timer_routine) (int, void *))
{
#ifdef CONFIG_TICK_SOURCE_SYSTMR0
setup_system_timer0();
#else
setup_core_timer();
#endif
bfin_timer_irq.handler = (irq_handler_t)timer_routine;
/* call setup_irq instead of request_irq because request_irq calls
* kmalloc which has not been initialized yet
*/
#ifdef CONFIG_TICK_SOURCE_SYSTMR0
setup_irq(IRQ_TIMER0, &bfin_timer_irq);
#else
setup_irq(IRQ_CORETMR, &bfin_timer_irq);
#endif
}
/*
......@@ -87,17 +121,23 @@ static unsigned long gettimeoffset(void)
unsigned long offset;
unsigned long clocks_per_jiffy;
#ifdef CONFIG_TICK_SOURCE_SYSTMR0
clocks_per_jiffy = bfin_read_TIMER0_PERIOD();
offset = bfin_read_TIMER0_COUNTER() / \
(((clocks_per_jiffy + 1) * HZ) / USEC_PER_SEC);
if ((get_gptimer_status(0) & TIMER_STATUS_TIMIL0) && offset < (100000 / HZ / 2))
offset += (USEC_PER_SEC / HZ);
#else
clocks_per_jiffy = bfin_read_TPERIOD();
offset =
(clocks_per_jiffy -
bfin_read_TCOUNT()) / (((clocks_per_jiffy + 1) * HZ) /
USEC_PER_SEC);
offset = (clocks_per_jiffy - bfin_read_TCOUNT()) / \
(((clocks_per_jiffy + 1) * HZ) / USEC_PER_SEC);
/* Check if we just wrapped the counters and maybe missed a tick */
if ((bfin_read_ILAT() & (1 << IRQ_CORETMR))
&& (offset < (100000 / HZ / 2)))
&& (offset < (100000 / HZ / 2)))
offset += (USEC_PER_SEC / HZ);
#endif
return offset;
}
......@@ -120,34 +160,38 @@ irqreturn_t timer_interrupt(int irq, void *dummy)
static long last_rtc_update;
write_seqlock(&xtime_lock);
do_timer(1);
profile_tick(CPU_PROFILING);
/*
* If we have an externally synchronized Linux clock, then update
* CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
* called as close as possible to 500 ms before the new second starts.
*/
if (ntp_synced() &&
xtime.tv_sec > last_rtc_update + 660 &&
(xtime.tv_nsec / NSEC_PER_USEC) >=
500000 - ((unsigned)TICK_SIZE) / 2
&& (xtime.tv_nsec / NSEC_PER_USEC) <=
500000 + ((unsigned)TICK_SIZE) / 2) {
if (set_rtc_mmss(xtime.tv_sec) == 0)
last_rtc_update = xtime.tv_sec;
else
/* Do it again in 60s. */
last_rtc_update = xtime.tv_sec - 600;
#ifdef CONFIG_TICK_SOURCE_SYSTMR0
if (get_gptimer_status(0) & TIMER_STATUS_TIMIL0) {
#endif
do_timer(1);
/*
* If we have an externally synchronized Linux clock, then update
* CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
* called as close as possible to 500 ms before the new second starts.
*/
if (ntp_synced() &&
xtime.tv_sec > last_rtc_update + 660 &&
(xtime.tv_nsec / NSEC_PER_USEC) >=
500000 - ((unsigned)TICK_SIZE) / 2
&& (xtime.tv_nsec / NSEC_PER_USEC) <=
500000 + ((unsigned)TICK_SIZE) / 2) {
if (set_rtc_mmss(xtime.tv_sec) == 0)
last_rtc_update = xtime.tv_sec;
else
/* Do it again in 60s. */
last_rtc_update = xtime.tv_sec - 600;
}
#ifdef CONFIG_TICK_SOURCE_SYSTMR0
set_gptimer_status(0, TIMER_STATUS_TIMIL0);
}
#endif
write_sequnlock(&xtime_lock);
#ifndef CONFIG_SMP
update_process_times(user_mode(get_irq_regs()));
#endif
profile_tick(CPU_PROFILING);
return IRQ_HANDLED;
}
......
......@@ -75,16 +75,6 @@ void __init trap_init(void)
CSYNC();
}
/*
* Used to save the RETX, SEQSTAT, I/D CPLB FAULT ADDR
* values across the transition from exception to IRQ5.
* We put these in L1, so they are going to be in a valid
* location during exception context
*/
__attribute__((l1_data))
unsigned long saved_retx, saved_seqstat,
saved_icplb_fault_addr, saved_dcplb_fault_addr;
static void decode_address(char *buf, unsigned long address)
{
#ifdef CONFIG_DEBUG_VERBOSE
......@@ -211,18 +201,18 @@ asmlinkage void double_fault_c(struct pt_regs *fp)
printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n");
#ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT
if (((long)fp->seqstat & SEQSTAT_EXCAUSE) == VEC_UNCOV) {
unsigned int cpu = smp_processor_id();
char buf[150];
decode_address(buf, saved_retx);
decode_address(buf, cpu_pda[cpu].retx);
printk(KERN_EMERG "While handling exception (EXCAUSE = 0x%x) at %s:\n",
(int)saved_seqstat & SEQSTAT_EXCAUSE, buf);
decode_address(buf, saved_dcplb_fault_addr);
(unsigned int)cpu_pda[cpu].seqstat & SEQSTAT_EXCAUSE, buf);
decode_address(buf, cpu_pda[cpu].dcplb_fault_addr);
printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %s\n", buf);
decode_address(buf, saved_icplb_fault_addr);
decode_address(buf, cpu_pda[cpu].icplb_fault_addr);
printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %s\n", buf);
decode_address(buf, fp->retx);
printk(KERN_NOTICE "The instruction at %s caused a double exception\n",
buf);
printk(KERN_NOTICE "The instruction at %s caused a double exception\n", buf);
} else
#endif
{
......@@ -239,6 +229,9 @@ asmlinkage void trap_c(struct pt_regs *fp)
{
#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
int j;
#endif
#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
unsigned int cpu = smp_processor_id();
#endif
int sig = 0;
siginfo_t info;
......@@ -417,7 +410,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
info.si_code = ILL_CPLB_MULHIT;
sig = SIGSEGV;
#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
if (saved_dcplb_fault_addr < FIXED_CODE_START)
if (cpu_pda[cpu].dcplb_fault_addr < FIXED_CODE_START)
verbose_printk(KERN_NOTICE "NULL pointer access\n");
else
#endif
......@@ -471,7 +464,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
info.si_code = ILL_CPLB_MULHIT;
sig = SIGSEGV;
#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
if (saved_icplb_fault_addr < FIXED_CODE_START)
if (cpu_pda[cpu].icplb_fault_addr < FIXED_CODE_START)
verbose_printk(KERN_NOTICE "Jump to NULL address\n");
else
#endif
......@@ -960,6 +953,7 @@ void dump_bfin_process(struct pt_regs *fp)
else
verbose_printk(KERN_NOTICE "COMM= invalid\n");
printk(KERN_NOTICE "CPU = %d\n", current_thread_info()->cpu);
if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START)
verbose_printk(KERN_NOTICE "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n"
KERN_NOTICE " BSS = 0x%p-0x%p USER-STACK = 0x%p\n"
......@@ -1053,6 +1047,7 @@ void show_regs(struct pt_regs *fp)
struct irqaction *action;
unsigned int i;
unsigned long flags;
unsigned int cpu = smp_processor_id();
verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted());
verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n",
......@@ -1112,9 +1107,9 @@ unlock:
if (((long)fp->seqstat & SEQSTAT_EXCAUSE) &&
(((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) {
decode_address(buf, saved_dcplb_fault_addr);
decode_address(buf, cpu_pda[cpu].dcplb_fault_addr);
verbose_printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf);
decode_address(buf, saved_icplb_fault_addr);
decode_address(buf, cpu_pda[cpu].icplb_fault_addr);
verbose_printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf);
}
......@@ -1153,20 +1148,21 @@ unlock:
asmlinkage int sys_bfin_spinlock(int *spinlock)__attribute__((l1_text));
#endif
asmlinkage int sys_bfin_spinlock(int *spinlock)
static DEFINE_SPINLOCK(bfin_spinlock_lock);
asmlinkage int sys_bfin_spinlock(int *p)
{
int ret = 0;
int tmp = 0;
int ret, tmp = 0;
local_irq_disable();
ret = get_user(tmp, spinlock);
if (ret == 0) {
if (tmp)
spin_lock(&bfin_spinlock_lock); /* This would also hold kernel preemption. */
ret = get_user(tmp, p);
if (likely(ret == 0)) {
if (unlikely(tmp))
ret = 1;
tmp = 1;
put_user(tmp, spinlock);
else
put_user(1, p);
}
local_irq_enable();
spin_unlock(&bfin_spinlock_lock);
return ret;
}
......
......@@ -31,7 +31,8 @@
#include <linux/bootmem.h>
#include <linux/uaccess.h>
#include <asm/bfin-global.h>
#include <asm/l1layout.h>
#include <asm/pda.h>
#include <asm/cplbinit.h>
#include "blackfin_sram.h"
/*
......@@ -53,6 +54,11 @@ static unsigned long empty_bad_page;
unsigned long empty_zero_page;
extern unsigned long exception_stack[NR_CPUS][1024];
struct blackfin_pda cpu_pda[NR_CPUS];
EXPORT_SYMBOL(cpu_pda);
/*
* paging_init() continues the virtual memory environment setup which
* was begun by the code in arch/head.S.
......@@ -98,6 +104,42 @@ void __init paging_init(void)
}
}
asmlinkage void init_pda(void)
{
unsigned int cpu = raw_smp_processor_id();
/* Initialize the PDA fields holding references to other parts
of the memory. The content of such memory is still
undefined at the time of the call, we are only setting up
valid pointers to it. */
memset(&cpu_pda[cpu], 0, sizeof(cpu_pda[cpu]));
cpu_pda[0].next = &cpu_pda[1];
cpu_pda[1].next = &cpu_pda[0];
cpu_pda[cpu].ex_stack = exception_stack[cpu + 1];
#ifdef CONFIG_MPU
#else
cpu_pda[cpu].ipdt = ipdt_tables[cpu];
cpu_pda[cpu].dpdt = dpdt_tables[cpu];
#ifdef CONFIG_CPLB_INFO
cpu_pda[cpu].ipdt_swapcount = ipdt_swapcount_tables[cpu];
cpu_pda[cpu].dpdt_swapcount = dpdt_swapcount_tables[cpu];
#endif
#endif
#ifdef CONFIG_SMP
cpu_pda[cpu].imask = 0x1f;
#endif
}
void __cpuinit reserve_pda(void)
{
printk(KERN_INFO "PDA for CPU%u reserved at %p\n", smp_processor_id(),
&cpu_pda[smp_processor_id()]);
}
void __init mem_init(void)
{
unsigned int codek = 0, datak = 0, initk = 0;
......@@ -141,21 +183,13 @@ void __init mem_init(void)
static int __init sram_init(void)
{
unsigned long tmp;
/* Initialize the blackfin L1 Memory. */
bfin_sram_init();
/* Allocate this once; never free it. We assume this gives us a
pointer to the start of L1 scratchpad memory; panic if it
doesn't. */
tmp = (unsigned long)l1sram_alloc(sizeof(struct l1_scratch_task_info));
if (tmp != (unsigned long)L1_SCRATCH_TASK_INFO) {
printk(KERN_EMERG "mem_init(): Did not get the right address from l1sram_alloc: %08lx != %08lx\n",
tmp, (unsigned long)L1_SCRATCH_TASK_INFO);
panic("No L1, time to give up\n");
}
/* Reserve the PDA space for the boot CPU right after we
* initialized the scratch memory allocator.
*/
reserve_pda();
return 0;
}
pure_initcall(sram_init);
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment