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 41d2db6610219cbcadceea6c43ee03d89068b7d759Mitsuo Hayasaka#define STACK_TOP_MARGIN 128 4237fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka struct orig_ist *oist; 4337fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka u64 irq_stack_top, irq_stack_bottom; 4437fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka u64 estack_top, estack_bottom; 45c9f4f06d3191bd91c1a081b54a6c8e913e7b8a83Roman Zippel u64 curbase = (u64)task_stack_page(current); 46f377fa123d0ec621e8e361ecc3f2a8ee70e81a2eIngo Molnar 4769682b625a043b567873e6cda397969b502f0054Mitsuo Hayasaka if (user_mode_vm(regs)) 4869682b625a043b567873e6cda397969b502f0054Mitsuo Hayasaka return; 4969682b625a043b567873e6cda397969b502f0054Mitsuo Hayasaka 50467e6b7a7c0eb792ebaf322ddb7363742b4ead40Mitsuo Hayasaka if (regs->sp >= curbase + sizeof(struct thread_info) + 51d2db6610219cbcadceea6c43ee03d89068b7d759Mitsuo Hayasaka sizeof(struct pt_regs) + STACK_TOP_MARGIN && 52467e6b7a7c0eb792ebaf322ddb7363742b4ead40Mitsuo Hayasaka regs->sp <= curbase + THREAD_SIZE) 5337fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka return; 5437fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka 5589cbc76768c2fa4ed95545bf961f3a14ddfeed21Christoph Lameter irq_stack_top = (u64)this_cpu_ptr(irq_stack_union.irq_stack) + 56d2db6610219cbcadceea6c43ee03d89068b7d759Mitsuo Hayasaka STACK_TOP_MARGIN; 5789cbc76768c2fa4ed95545bf961f3a14ddfeed21Christoph Lameter irq_stack_bottom = (u64)__this_cpu_read(irq_stack_ptr); 5837fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka if (regs->sp >= irq_stack_top && regs->sp <= irq_stack_bottom) 5937fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka return; 6037fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka 6189cbc76768c2fa4ed95545bf961f3a14ddfeed21Christoph Lameter oist = this_cpu_ptr(&orig_ist); 62d2db6610219cbcadceea6c43ee03d89068b7d759Mitsuo Hayasaka estack_top = (u64)oist->ist[0] - EXCEPTION_STKSZ + STACK_TOP_MARGIN; 6337fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka estack_bottom = (u64)oist->ist[N_EXCEPTION_STACKS - 1]; 6437fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka if (regs->sp >= estack_top && regs->sp <= estack_bottom) 6537fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka return; 66f377fa123d0ec621e8e361ecc3f2a8ee70e81a2eIngo Molnar 6737fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo 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", 6837fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka current->comm, curbase, regs->sp, 6937fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka irq_stack_top, irq_stack_bottom, 7037fe6a42b3433b79a159ceb06a94cd1ef00e279dMitsuo Hayasaka estack_top, estack_bottom); 7155af77969fbd7a841838220ea2287432e0da8ae5Mitsuo Hayasaka 7255af77969fbd7a841838220ea2287432e0da8ae5Mitsuo Hayasaka if (sysctl_panic_on_stackoverflow) 7355af77969fbd7a841838220ea2287432e0da8ae5Mitsuo Hayasaka panic("low stack detected by irq handler - check messages\n"); 744961f10e2205d0ededa291e12ec634efc58aa93cEric Sandeen#endif 75f377fa123d0ec621e8e361ecc3f2a8ee70e81a2eIngo Molnar} 764961f10e2205d0ededa291e12ec634efc58aa93cEric Sandeen 779b2b76a3344146c4d8d300874e73af8161204f87Jeremy Fitzhardingebool handle_irq(unsigned irq, struct pt_regs *regs) 789b2b76a3344146c4d8d300874e73af8161204f87Jeremy Fitzhardinge{ 799b2b76a3344146c4d8d300874e73af8161204f87Jeremy Fitzhardinge struct irq_desc *desc; 809b2b76a3344146c4d8d300874e73af8161204f87Jeremy Fitzhardinge 819b2b76a3344146c4d8d300874e73af8161204f87Jeremy Fitzhardinge stack_overflow_check(regs); 829b2b76a3344146c4d8d300874e73af8161204f87Jeremy Fitzhardinge 839b2b76a3344146c4d8d300874e73af8161204f87Jeremy Fitzhardinge desc = irq_to_desc(irq); 849b2b76a3344146c4d8d300874e73af8161204f87Jeremy Fitzhardinge if (unlikely(!desc)) 859b2b76a3344146c4d8d300874e73af8161204f87Jeremy Fitzhardinge return false; 869b2b76a3344146c4d8d300874e73af8161204f87Jeremy Fitzhardinge 879b2b76a3344146c4d8d300874e73af8161204f87Jeremy Fitzhardinge generic_handle_irq_desc(irq, desc); 889b2b76a3344146c4d8d300874e73af8161204f87Jeremy Fitzhardinge return true; 899b2b76a3344146c4d8d300874e73af8161204f87Jeremy Fitzhardinge} 90