xref: /openbmc/linux/arch/x86/kernel/doublefault_32.c (revision e99b6f46ee5c127d39d2f3a2682fdeef10386316)
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