irq_64.c revision 55af77969fbd7a841838220ea2287432e0da8ae5
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This file contains the lowest level x86_64-specific interrupt 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * entry and irq statistics code. All the remaining irq logic is 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * done by the generic kernel/irq/ code and in the 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * x86_64-specific irq controller code. (e.g. i8259.c and 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * io_apic.c.) 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel_stat.h> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/seq_file.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 1576e4f660d9f4c6d1bb473f72be2988c35eaca948Ashok Raj#include <linux/delay.h> 16bcbc4f20b52c2c40c43a4d2337707dcdfe81bc3aFrederic Weisbecker#include <linux/ftrace.h> 175f66b2a0d919e84ee921dc21c9dbfddd1215c0e9Jaswinder Singh Rajput#include <linux/uaccess.h> 185f66b2a0d919e84ee921dc21c9dbfddd1215c0e9Jaswinder Singh Rajput#include <linux/smp.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io_apic.h> 2095833c83f3b812c78e48db4eaa19f6c74958470bAndi Kleen#include <asm/idle.h> 213819cd489ec5d18a4cbd2f05acdc516473caa105Brian Gerst#include <asm/apic.h> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 231b437c8c73a36daa471dd54a63c426d72af5723dBrian GerstDEFINE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat); 241b437c8c73a36daa471dd54a63c426d72af5723dBrian GerstEXPORT_PER_CPU_SYMBOL(irq_stat); 251b437c8c73a36daa471dd54a63c426d72af5723dBrian Gerst 26d650a5148593b65a3c3f9a344f46b91b7dfe7713Brian GerstDEFINE_PER_CPU(struct pt_regs *, irq_regs); 27d650a5148593b65a3c3f9a344f46b91b7dfe7713Brian GerstEXPORT_PER_CPU_SYMBOL(irq_regs); 28d650a5148593b65a3c3f9a344f46b91b7dfe7713Brian Gerst 2955af77969fbd7a841838220ea2287432e0da8ae5Mitsuo Hayasakaint sysctl_panic_on_stackoverflow; 3055af77969fbd7a841838220ea2287432e0da8ae5Mitsuo Hayasaka 314961f10e2205d0ededa291e12ec634efc58aa93cEric Sandeen/* 324961f10e2205d0ededa291e12ec634efc58aa93cEric Sandeen * Probabilistic stack overflow check: 334961f10e2205d0ededa291e12ec634efc58aa93cEric Sandeen * 344961f10e2205d0ededa291e12ec634efc58aa93cEric Sandeen * Only check the stack in process context, because everything else 354961f10e2205d0ededa291e12ec634efc58aa93cEric Sandeen * runs on the big interrupt stacks. Checking reliably is too expensive, 364961f10e2205d0ededa291e12ec634efc58aa93cEric Sandeen * so we just check from interrupts. 374961f10e2205d0ededa291e12ec634efc58aa93cEric Sandeen */ 384961f10e2205d0ededa291e12ec634efc58aa93cEric Sandeenstatic inline void stack_overflow_check(struct pt_regs *regs) 394961f10e2205d0ededa291e12ec634efc58aa93cEric Sandeen{ 40f377fa123d0ec621e8e361ecc3f2a8ee70e81a2eIngo Molnar#ifdef CONFIG_DEBUG_STACKOVERFLOW 4137fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka struct orig_ist *oist; 4237fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka u64 irq_stack_top, irq_stack_bottom; 4337fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka u64 estack_top, estack_bottom; 44c9f4f06d3191bd91c1a081b54a6c8e913e7b8a83Roman Zippel u64 curbase = (u64)task_stack_page(current); 45f377fa123d0ec621e8e361ecc3f2a8ee70e81a2eIngo Molnar 4669682b625a043b567873e6cda397969b502f0054Mitsuo Hayasaka if (user_mode_vm(regs)) 4769682b625a043b567873e6cda397969b502f0054Mitsuo Hayasaka return; 4869682b625a043b567873e6cda397969b502f0054Mitsuo Hayasaka 4937fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka if (regs->sp >= curbase && 5037fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka regs->sp <= curbase + THREAD_SIZE && 5137fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka regs->sp >= curbase + sizeof(struct thread_info) + 5237fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka sizeof(struct pt_regs) + 128) 5337fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka return; 5437fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka 5537fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka irq_stack_top = (u64)__get_cpu_var(irq_stack_union.irq_stack); 5637fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka irq_stack_bottom = (u64)__get_cpu_var(irq_stack_ptr); 5737fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka if (regs->sp >= irq_stack_top && regs->sp <= irq_stack_bottom) 5837fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka return; 5937fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka 6037fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka oist = &__get_cpu_var(orig_ist); 6137fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka estack_top = (u64)oist->ist[0] - EXCEPTION_STKSZ; 6237fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka estack_bottom = (u64)oist->ist[N_EXCEPTION_STACKS - 1]; 6337fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka if (regs->sp >= estack_top && regs->sp <= estack_bottom) 6437fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka return; 65f377fa123d0ec621e8e361ecc3f2a8ee70e81a2eIngo Molnar 6637fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka WARN_ONCE(1, "do_IRQ(): %s has overflown the kernel stack (cur:%Lx,sp:%lx,irq stk top-bottom:%Lx-%Lx,exception stk top-bottom:%Lx-%Lx)\n", 6737fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka current->comm, curbase, regs->sp, 6837fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka irq_stack_top, irq_stack_bottom, 6937fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka estack_top, estack_bottom); 7055af77969fbd7a841838220ea2287432e0da8ae5Mitsuo Hayasaka 7155af77969fbd7a841838220ea2287432e0da8ae5Mitsuo Hayasaka if (sysctl_panic_on_stackoverflow) 7255af77969fbd7a841838220ea2287432e0da8ae5Mitsuo Hayasaka panic("low stack detected by irq handler - check messages\n"); 734961f10e2205d0ededa291e12ec634efc58aa93cEric Sandeen#endif 74f377fa123d0ec621e8e361ecc3f2a8ee70e81a2eIngo Molnar} 754961f10e2205d0ededa291e12ec634efc58aa93cEric Sandeen 769b2b76a3344146c4d8d300874e73af8161204f87Jeremy Fitzhardingebool handle_irq(unsigned irq, struct pt_regs *regs) 779b2b76a3344146c4d8d300874e73af8161204f87Jeremy Fitzhardinge{ 789b2b76a3344146c4d8d300874e73af8161204f87Jeremy Fitzhardinge struct irq_desc *desc; 799b2b76a3344146c4d8d300874e73af8161204f87Jeremy Fitzhardinge 809b2b76a3344146c4d8d300874e73af8161204f87Jeremy Fitzhardinge stack_overflow_check(regs); 819b2b76a3344146c4d8d300874e73af8161204f87Jeremy Fitzhardinge 829b2b76a3344146c4d8d300874e73af8161204f87Jeremy Fitzhardinge desc = irq_to_desc(irq); 839b2b76a3344146c4d8d300874e73af8161204f87Jeremy Fitzhardinge if (unlikely(!desc)) 849b2b76a3344146c4d8d300874e73af8161204f87Jeremy Fitzhardinge return false; 859b2b76a3344146c4d8d300874e73af8161204f87Jeremy Fitzhardinge 869b2b76a3344146c4d8d300874e73af8161204f87Jeremy Fitzhardinge generic_handle_irq_desc(irq, desc); 879b2b76a3344146c4d8d300874e73af8161204f87Jeremy Fitzhardinge return true; 889b2b76a3344146c4d8d300874e73af8161204f87Jeremy Fitzhardinge} 899b2b76a3344146c4d8d300874e73af8161204f87Jeremy Fitzhardinge 90ed6b676ca8b50e0b538e61c283d52fd04f007abfAndi Kleen 91ed6b676ca8b50e0b538e61c283d52fd04f007abfAndi Kleenextern void call_softirq(void); 92ed6b676ca8b50e0b538e61c283d52fd04f007abfAndi Kleen 93ed6b676ca8b50e0b538e61c283d52fd04f007abfAndi Kleenasmlinkage void do_softirq(void) 94ed6b676ca8b50e0b538e61c283d52fd04f007abfAndi Kleen{ 955f66b2a0d919e84ee921dc21c9dbfddd1215c0e9Jaswinder Singh Rajput __u32 pending; 965f66b2a0d919e84ee921dc21c9dbfddd1215c0e9Jaswinder Singh Rajput unsigned long flags; 97ed6b676ca8b50e0b538e61c283d52fd04f007abfAndi Kleen 985f66b2a0d919e84ee921dc21c9dbfddd1215c0e9Jaswinder Singh Rajput if (in_interrupt()) 995f66b2a0d919e84ee921dc21c9dbfddd1215c0e9Jaswinder Singh Rajput return; 100ed6b676ca8b50e0b538e61c283d52fd04f007abfAndi Kleen 1015f66b2a0d919e84ee921dc21c9dbfddd1215c0e9Jaswinder Singh Rajput local_irq_save(flags); 1025f66b2a0d919e84ee921dc21c9dbfddd1215c0e9Jaswinder Singh Rajput pending = local_softirq_pending(); 1035f66b2a0d919e84ee921dc21c9dbfddd1215c0e9Jaswinder Singh Rajput /* Switch to interrupt stack */ 1045f66b2a0d919e84ee921dc21c9dbfddd1215c0e9Jaswinder Singh Rajput if (pending) { 105ed6b676ca8b50e0b538e61c283d52fd04f007abfAndi Kleen call_softirq(); 1062601e64d262ee5ed4d4a5737345803800d9c4db3Ingo Molnar WARN_ON_ONCE(softirq_count()); 1072601e64d262ee5ed4d4a5737345803800d9c4db3Ingo Molnar } 1085f66b2a0d919e84ee921dc21c9dbfddd1215c0e9Jaswinder Singh Rajput local_irq_restore(flags); 109ed6b676ca8b50e0b538e61c283d52fd04f007abfAndi Kleen} 110