2005-04-17 02:20:36 +04:00
# include <linux/mm.h>
# include <linux/sched.h>
# include <linux/init_task.h>
# include <linux/fs.h>
2016-12-24 22:46:01 +03:00
# include <linux/uaccess.h>
2005-04-17 02:20:36 +04:00
# include <asm/pgtable.h>
# include <asm/processor.h>
# include <asm/desc.h>
2013-05-09 14:02:29 +04:00
# ifdef CONFIG_X86_32
2005-04-17 02:20:36 +04:00
# define DOUBLEFAULT_STACKSIZE (1024)
static unsigned long doublefault_stack [ DOUBLEFAULT_STACKSIZE ] ;
# define STACK_START (unsigned long)(doublefault_stack+DOUBLEFAULT_STACKSIZE)
2007-08-11 00:31:11 +04:00
# define ptr_ok(x) ((x) > PAGE_OFFSET && (x) < PAGE_OFFSET + MAXMEM)
2005-04-17 02:20:36 +04:00
static void doublefault_fn ( void )
{
2008-01-30 15:31:12 +03:00
struct desc_ptr gdt_desc = { 0 , 0 } ;
2005-04-17 02:20:36 +04:00
unsigned long gdt , tss ;
2013-04-06 00:42:23 +04:00
native_store_gdt ( & gdt_desc ) ;
2005-04-17 02:20:36 +04:00
gdt = gdt_desc . address ;
2007-08-11 00:31:11 +04:00
printk ( KERN_EMERG " PANIC: double fault, gdt at %08lx [%d bytes] \n " , gdt , gdt_desc . size ) ;
2005-04-17 02:20:36 +04:00
if ( ptr_ok ( gdt ) ) {
gdt + = GDT_ENTRY_TSS < < 3 ;
2009-07-18 19:08:54 +04:00
tss = get_desc_base ( ( struct desc_struct * ) gdt ) ;
2007-08-11 00:31:11 +04:00
printk ( KERN_EMERG " double fault, tss at %08lx \n " , tss ) ;
2005-04-17 02:20:36 +04:00
if ( ptr_ok ( tss ) ) {
2008-01-30 15:31:31 +03:00
struct x86_hw_tss * t = ( struct x86_hw_tss * ) tss ;
2005-04-17 02:20:36 +04:00
2008-01-30 15:31:02 +03:00
printk ( KERN_EMERG " eip = %08lx, esp = %08lx \n " ,
t - > ip , t - > sp ) ;
2005-04-17 02:20:36 +04:00
2007-08-11 00:31:11 +04:00
printk ( KERN_EMERG " eax = %08lx, ebx = %08lx, ecx = %08lx, edx = %08lx \n " ,
2008-01-30 15:31:02 +03:00
t - > ax , t - > bx , t - > cx , t - > dx ) ;
2007-08-11 00:31:11 +04:00
printk ( KERN_EMERG " esi = %08lx, edi = %08lx \n " ,
2008-01-30 15:31:02 +03:00
t - > si , t - > di ) ;
2005-04-17 02:20:36 +04:00
}
}
2006-06-25 16:46:53 +04:00
for ( ; ; )
cpu_relax ( ) ;
2005-04-17 02:20:36 +04:00
}
struct tss_struct doublefault_tss __cacheline_aligned = {
2007-05-02 21:27:13 +04:00
. x86_tss = {
2008-01-30 15:31:02 +03:00
. sp0 = STACK_START ,
2007-05-02 21:27:13 +04:00
. ss0 = __KERNEL_DS ,
. ldt = 0 ,
. io_bitmap_base = INVALID_IO_BITMAP_OFFSET ,
2005-04-17 02:20:36 +04:00
2008-01-30 15:31:02 +03:00
. ip = ( unsigned long ) doublefault_fn ,
2007-05-02 21:27:13 +04:00
/* 0x2 bit is always set */
2008-01-30 15:31:02 +03:00
. flags = X86_EFLAGS_SF | 0x2 ,
. sp = STACK_START ,
2007-05-02 21:27:13 +04:00
. es = __USER_DS ,
. cs = __KERNEL_CS ,
. ss = __KERNEL_DS ,
. ds = __USER_DS ,
2007-08-11 00:31:11 +04:00
. fs = __KERNEL_PERCPU ,
2005-04-17 02:20:36 +04:00
2008-10-03 19:54:25 +04:00
. __cr3 = __pa_nodebug ( swapper_pg_dir ) ,
2007-05-02 21:27:13 +04:00
}
2005-04-17 02:20:36 +04:00
} ;
2013-05-09 14:02:29 +04:00
/* dummy for do_double_fault() call */
void df_debug ( struct pt_regs * regs , long error_code ) { }
# else /* !CONFIG_X86_32 */
void df_debug ( struct pt_regs * regs , long error_code )
{
pr_emerg ( " PANIC: double fault, error_code: 0x%lx \n " , error_code ) ;
show_regs ( regs ) ;
panic ( " Machine halted. " ) ;
}
# endif