diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-03-07 15:45:24 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-03-07 15:45:24 +0000 |
commit | 9f9f3e6e8548a596697778337110a423c384b6f3 (patch) | |
tree | 5dd4b290ef532cf5ecb058e1a92cd3435afeac8c /arch/sparc64/kernel/smp.c | |
parent | d5c9a365ee7d2fded249aa5abfc5e89587583029 (diff) |
Merge with Linux 2.3.49.
Diffstat (limited to 'arch/sparc64/kernel/smp.c')
-rw-r--r-- | arch/sparc64/kernel/smp.c | 106 |
1 files changed, 93 insertions, 13 deletions
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index 273c12de1..175372877 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -119,6 +119,7 @@ extern void cpu_probe(void); void __init smp_callin(void) { int cpuid = hard_smp_processor_id(); + unsigned long pstate; inherit_locked_prom_mappings(0); @@ -127,18 +128,37 @@ void __init smp_callin(void) cpu_probe(); - /* Master did this already, now is the time for us to do it. */ + /* Guarentee that the following sequences execute + * uninterrupted. + */ + __asm__ __volatile__("rdpr %%pstate, %0\n\t" + "wrpr %0, %1, %%pstate" + : "=r" (pstate) + : "i" (PSTATE_IE)); + + /* Set things up so user can access tick register for profiling + * purposes. Also workaround BB_ERRATA_1 by doing a dummy + * read back of %tick after writing it. + */ __asm__ __volatile__(" sethi %%hi(0x80000000), %%g1 - sllx %%g1, 32, %%g1 - rd %%tick, %%g2 + ba,pt %%xcc, 1f + sllx %%g1, 32, %%g1 + .align 64 +1: rd %%tick, %%g2 add %%g2, 6, %%g2 andn %%g2, %%g1, %%g2 wrpr %%g2, 0, %%tick -" : /* no outputs */ + rdpr %%tick, %%g0" + : /* no outputs */ : /* no inputs */ : "g1", "g2"); + /* Restore PSTATE_IE. */ + __asm__ __volatile__("wrpr %0, 0x0, %%pstate" + : /* no outputs */ + : "r" (pstate)); + smp_setup_percpu_timer(); __sti(); @@ -598,7 +618,7 @@ extern void update_one_process(struct task_struct *p, unsigned long ticks, void smp_percpu_timer_interrupt(struct pt_regs *regs) { - unsigned long compare, tick; + unsigned long compare, tick, pstate; int cpu = smp_processor_id(); int user = user_mode(regs); @@ -664,27 +684,87 @@ do { hardirq_enter(cpu); \ prof_counter(cpu) = prof_multiplier(cpu); } + /* Guarentee that the following sequences execute + * uninterrupted. + */ + __asm__ __volatile__("rdpr %%pstate, %0\n\t" + "wrpr %0, %1, %%pstate" + : "=r" (pstate) + : "i" (PSTATE_IE)); + + /* Workaround for Spitfire Errata (#54 I think??), I discovered + * this via Sun BugID 4008234, mentioned in Solaris-2.5.1 patch + * number 103640. + * + * On Blackbird writes to %tick_cmpr can fail, the + * workaround seems to be to execute the wr instruction + * at the start of an I-cache line, and perform a dummy + * read back from %tick_cmpr right after writing to it. -DaveM + * + * Just to be anal we add a workaround for Spitfire + * Errata 50 by preventing pipeline bypasses on the + * final read of the %tick register into a compare + * instruction. The Errata 50 description states + * that %tick is not prone to this bug, but I am not + * taking any chances. + */ __asm__ __volatile__("rd %%tick_cmpr, %0\n\t" - "add %0, %2, %0\n\t" - "wr %0, 0x0, %%tick_cmpr\n\t" - "rd %%tick, %1" + "ba,pt %%xcc, 1f\n\t" + " add %0, %2, %0\n\t" + ".align 64\n" + "1: wr %0, 0x0, %%tick_cmpr\n\t" + "rd %%tick_cmpr, %%g0\n\t" + "rd %%tick, %1\n\t" + "mov %1, %1" : "=&r" (compare), "=r" (tick) : "r" (current_tick_offset)); + + /* Restore PSTATE_IE. */ + __asm__ __volatile__("wrpr %0, 0x0, %%pstate" + : /* no outputs */ + : "r" (pstate)); } while (tick >= compare); } static void __init smp_setup_percpu_timer(void) { int cpu = smp_processor_id(); + unsigned long pstate; prof_counter(cpu) = prof_multiplier(cpu) = 1; - __asm__ __volatile__("rd %%tick, %%g1\n\t" - "add %%g1, %0, %%g1\n\t" - "wr %%g1, 0x0, %%tick_cmpr" + /* Guarentee that the following sequences execute + * uninterrupted. + */ + __asm__ __volatile__("rdpr %%pstate, %0\n\t" + "wrpr %0, %1, %%pstate" + : "=r" (pstate) + : "i" (PSTATE_IE)); + + /* Workaround for Spitfire Errata (#54 I think??), I discovered + * this via Sun BugID 4008234, mentioned in Solaris-2.5.1 patch + * number 103640. + * + * On Blackbird writes to %tick_cmpr can fail, the + * workaround seems to be to execute the wr instruction + * at the start of an I-cache line, and perform a dummy + * read back from %tick_cmpr right after writing to it. -DaveM + */ + __asm__ __volatile__(" + rd %%tick, %%g1 + ba,pt %%xcc, 1f + add %%g1, %0, %%g1 + .align 64 + 1: wr %%g1, 0x0, %%tick_cmpr + rd %%tick_cmpr, %%g0" + : /* no outputs */ + : "r" (current_tick_offset) + : "g1"); + + /* Restore PSTATE_IE. */ + __asm__ __volatile__("wrpr %0, 0x0, %%pstate" : /* no outputs */ - : "r" (current_tick_offset) - : "g1"); + : "r" (pstate)); } void __init smp_tick_init(void) |