33 #include <linux/export.h>
36 #include <linux/signal.h>
37 #include <linux/sched.h>
38 #include <linux/ptrace.h>
41 #include <linux/timex.h>
43 #include <linux/slab.h>
49 #include <linux/bitops.h>
50 #include <linux/list.h>
54 #include <linux/pci.h>
59 #include <asm/uaccess.h>
61 #include <asm/pgtable.h>
63 #include <asm/cache.h>
65 #include <asm/ptrace.h>
66 #include <asm/machdep.h>
69 #include <asm/debug.h>
76 #define CREATE_TRACE_POINTS
77 #include <asm/trace.h>
96 int distribute_irqs = 1;
98 static inline notrace unsigned long get_irq_happened(
void)
100 unsigned long happened;
102 __asm__ __volatile__(
"lbz %0,%1(13)"
103 :
"=r" (happened) :
"i" (
offsetof(
struct paca_struct, irq_happened)));
108 static inline notrace void set_soft_enabled(
unsigned long enable)
110 __asm__ __volatile__(
"stb %0,%1(13)"
111 : :
"r" (enable),
"i" (
offsetof(
struct paca_struct, soft_enabled)));
114 static inline notrace int decrementer_check_overflow(
void)
116 u64 now = get_tb_or_rtc();
121 return now >= *next_tb;
138 notrace unsigned int __check_irq_replay(
void)
145 unsigned char happened = local_paca->irq_happened;
148 local_paca->irq_happened &= ~PACA_IRQ_HARD_DIS;
154 if (firmware_has_feature(FW_FEATURE_PS3_LV1)) {
156 lv1_get_version_info(&tmp, &tmp2);
164 local_paca->irq_happened &= ~PACA_IRQ_DEC;
165 if (decrementer_check_overflow())
169 local_paca->irq_happened &= ~PACA_IRQ_EE;
170 if (happened & PACA_IRQ_EE)
173 #ifdef CONFIG_PPC_BOOK3E
178 local_paca->irq_happened &= ~PACA_IRQ_EE_EDGE;
179 if (happened & PACA_IRQ_EE_EDGE)
182 local_paca->irq_happened &= ~PACA_IRQ_DBELL;
183 if (happened & PACA_IRQ_DBELL)
188 BUG_ON(local_paca->irq_happened != 0);
195 unsigned char irq_happened;
199 set_soft_enabled(en);
215 irq_happened = get_irq_happened();
230 if (
unlikely(irq_happened != PACA_IRQ_HARD_DIS))
231 __hard_irq_disable();
232 #ifdef CONFIG_TRACE_IRQFLAGS
241 __hard_irq_disable();
252 replay = __check_irq_replay();
262 __replay_interrupt(replay);
280 void notrace restore_interrupts(
void)
283 local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
304 bool prep_irq_for_idle(
void)
316 if (lazy_irq_pending())
328 local_paca->irq_happened &= ~PACA_IRQ_HARD_DIS;
329 local_paca->soft_enabled = 1;
341 #if defined(CONFIG_PPC32) && defined(CONFIG_TAU_INT)
346 seq_puts(p,
" PowerPC Thermal Assist (cpu temp)\n");
363 seq_printf(p,
" Performance monitoring interrupts\n");
387 #ifdef CONFIG_HOTPLUG_CPU
402 data = irq_desc_get_irq_data(desc);
403 if (irqd_is_per_cpu(data))
406 chip = irq_data_get_irq_chip(data);
408 cpumask_and(mask, data->
affinity, map);
410 printk(
"Breaking affinity for irq %i\n", irq);
411 cpumask_copy(mask, map);
415 else if (desc->
action && !(warned++))
416 printk(
"Cannot set affinity for irq %i\n", irq);
419 free_cpumask_var(mask);
427 static inline void handle_one_irq(
unsigned int irq)
430 unsigned long saved_sp_limit;
441 if (curtp == irqtp) {
447 saved_sp_limit =
current->thread.ksp_limit;
460 call_handle_irq(irq, desc, irqtp, desc->
handle_irq);
461 current->thread.ksp_limit = saved_sp_limit;
471 static inline void check_stack_overflow(
void)
473 #ifdef CONFIG_DEBUG_STACKOVERFLOW
480 printk(
"do_IRQ: stack overflow: %ld\n",
489 struct pt_regs *old_regs = set_irq_regs(regs);
494 trace_irq_entry(regs);
496 check_stack_overflow();
506 may_hard_irq_enable();
514 trace_irq_exit(regs);
517 set_irq_regs(old_regs);
530 #if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
535 void exc_lvl_ctx_init(
void)
544 cpu_nr = get_hard_smp_processor_id(i);
547 tp = critirq_ctx[cpu_nr];
553 tp = dbgirq_ctx[cpu_nr];
558 tp = mcheckirq_ctx[cpu_nr];
587 static inline void do_softirq_onstack(
void)
590 unsigned long saved_sp_limit =
current->thread.ksp_limit;
598 call_do_softirq(irqtp);
599 current->thread.ksp_limit = saved_sp_limit;
619 do_softirq_onstack();
636 if (cpumask_equal(mask, cpu_online_mask)) {
637 static int irq_rover;
645 irq_rover = cpumask_next(irq_rover, cpu_online_mask);
646 if (irq_rover >= nr_cpu_ids)
647 irq_rover = cpumask_first(cpu_online_mask);
654 if (cpuid >= nr_cpu_ids)
658 return get_hard_smp_processor_id(cpuid);
673 static int __init setup_noirqdistrib(
char *
str)
679 __setup(
"noirqdistrib", setup_noirqdistrib);