1*e99b6f46SAndy Lutomirski // SPDX-License-Identifier: GPL-2.0 2*e99b6f46SAndy Lutomirski #include <linux/mm.h> 3*e99b6f46SAndy Lutomirski #include <linux/sched.h> 4*e99b6f46SAndy Lutomirski #include <linux/sched/debug.h> 5*e99b6f46SAndy Lutomirski #include <linux/init_task.h> 6*e99b6f46SAndy Lutomirski #include <linux/fs.h> 7*e99b6f46SAndy Lutomirski 8*e99b6f46SAndy Lutomirski #include <linux/uaccess.h> 9*e99b6f46SAndy Lutomirski #include <asm/pgtable.h> 10*e99b6f46SAndy Lutomirski #include <asm/processor.h> 11*e99b6f46SAndy Lutomirski #include <asm/desc.h> 12*e99b6f46SAndy Lutomirski 13*e99b6f46SAndy Lutomirski #define DOUBLEFAULT_STACKSIZE (1024) 14*e99b6f46SAndy Lutomirski static unsigned long doublefault_stack[DOUBLEFAULT_STACKSIZE]; 15*e99b6f46SAndy Lutomirski #define STACK_START (unsigned long)(doublefault_stack+DOUBLEFAULT_STACKSIZE) 16*e99b6f46SAndy Lutomirski 17*e99b6f46SAndy Lutomirski #define ptr_ok(x) ((x) > PAGE_OFFSET && (x) < PAGE_OFFSET + MAXMEM) 18*e99b6f46SAndy Lutomirski 19*e99b6f46SAndy Lutomirski static void doublefault_fn(void) 20*e99b6f46SAndy Lutomirski { 21*e99b6f46SAndy Lutomirski struct desc_ptr gdt_desc = {0, 0}; 22*e99b6f46SAndy Lutomirski unsigned long gdt, tss; 23*e99b6f46SAndy Lutomirski 24*e99b6f46SAndy Lutomirski native_store_gdt(&gdt_desc); 25*e99b6f46SAndy Lutomirski gdt = gdt_desc.address; 26*e99b6f46SAndy Lutomirski 27*e99b6f46SAndy Lutomirski printk(KERN_EMERG "PANIC: double fault, gdt at %08lx [%d bytes]\n", gdt, gdt_desc.size); 28*e99b6f46SAndy Lutomirski 29*e99b6f46SAndy Lutomirski if (ptr_ok(gdt)) { 30*e99b6f46SAndy Lutomirski gdt += GDT_ENTRY_TSS << 3; 31*e99b6f46SAndy Lutomirski tss = get_desc_base((struct desc_struct *)gdt); 32*e99b6f46SAndy Lutomirski printk(KERN_EMERG "double fault, tss at %08lx\n", tss); 33*e99b6f46SAndy Lutomirski 34*e99b6f46SAndy Lutomirski if (ptr_ok(tss)) { 35*e99b6f46SAndy Lutomirski struct x86_hw_tss *t = (struct x86_hw_tss *)tss; 36*e99b6f46SAndy Lutomirski 37*e99b6f46SAndy Lutomirski printk(KERN_EMERG "eip = %08lx, esp = %08lx\n", 38*e99b6f46SAndy Lutomirski t->ip, t->sp); 39*e99b6f46SAndy Lutomirski 40*e99b6f46SAndy Lutomirski printk(KERN_EMERG "eax = %08lx, ebx = %08lx, ecx = %08lx, edx = %08lx\n", 41*e99b6f46SAndy Lutomirski t->ax, t->bx, t->cx, t->dx); 42*e99b6f46SAndy Lutomirski printk(KERN_EMERG "esi = %08lx, edi = %08lx\n", 43*e99b6f46SAndy Lutomirski t->si, t->di); 44*e99b6f46SAndy Lutomirski } 45*e99b6f46SAndy Lutomirski } 46*e99b6f46SAndy Lutomirski 47*e99b6f46SAndy Lutomirski for (;;) 48*e99b6f46SAndy Lutomirski cpu_relax(); 49*e99b6f46SAndy Lutomirski } 50*e99b6f46SAndy Lutomirski 51*e99b6f46SAndy Lutomirski struct x86_hw_tss doublefault_tss __cacheline_aligned = { 52*e99b6f46SAndy Lutomirski .sp0 = STACK_START, 53*e99b6f46SAndy Lutomirski .ss0 = __KERNEL_DS, 54*e99b6f46SAndy Lutomirski .ldt = 0, 55*e99b6f46SAndy Lutomirski .io_bitmap_base = IO_BITMAP_OFFSET_INVALID, 56*e99b6f46SAndy Lutomirski 57*e99b6f46SAndy Lutomirski .ip = (unsigned long) doublefault_fn, 58*e99b6f46SAndy Lutomirski /* 0x2 bit is always set */ 59*e99b6f46SAndy Lutomirski .flags = X86_EFLAGS_SF | 0x2, 60*e99b6f46SAndy Lutomirski .sp = STACK_START, 61*e99b6f46SAndy Lutomirski .es = __USER_DS, 62*e99b6f46SAndy Lutomirski .cs = __KERNEL_CS, 63*e99b6f46SAndy Lutomirski .ss = __KERNEL_DS, 64*e99b6f46SAndy Lutomirski .ds = __USER_DS, 65*e99b6f46SAndy Lutomirski .fs = __KERNEL_PERCPU, 66*e99b6f46SAndy Lutomirski #ifndef CONFIG_X86_32_LAZY_GS 67*e99b6f46SAndy Lutomirski .gs = __KERNEL_STACK_CANARY, 68*e99b6f46SAndy Lutomirski #endif 69*e99b6f46SAndy Lutomirski 70*e99b6f46SAndy Lutomirski .__cr3 = __pa_nodebug(swapper_pg_dir), 71*e99b6f46SAndy Lutomirski }; 72