1*7d36db35SAvi Kivity /* 2*7d36db35SAvi Kivity * Copyright 2010 Siemens AG 3*7d36db35SAvi Kivity * Author: Jan Kiszka 4*7d36db35SAvi Kivity * 5*7d36db35SAvi Kivity * Released under GPLv2. 6*7d36db35SAvi Kivity */ 7*7d36db35SAvi Kivity 8*7d36db35SAvi Kivity #include "libcflat.h" 9*7d36db35SAvi Kivity 10*7d36db35SAvi Kivity #define FIRST_SPARE_SEL 0x18 11*7d36db35SAvi Kivity 12*7d36db35SAvi Kivity struct exception_frame { 13*7d36db35SAvi Kivity unsigned long error_code; 14*7d36db35SAvi Kivity unsigned long ip; 15*7d36db35SAvi Kivity unsigned long cs; 16*7d36db35SAvi Kivity unsigned long flags; 17*7d36db35SAvi Kivity }; 18*7d36db35SAvi Kivity 19*7d36db35SAvi Kivity struct tss32 { 20*7d36db35SAvi Kivity unsigned short prev; 21*7d36db35SAvi Kivity unsigned short res1; 22*7d36db35SAvi Kivity unsigned long esp0; 23*7d36db35SAvi Kivity unsigned short ss0; 24*7d36db35SAvi Kivity unsigned short res2; 25*7d36db35SAvi Kivity unsigned long esp1; 26*7d36db35SAvi Kivity unsigned short ss1; 27*7d36db35SAvi Kivity unsigned short res3; 28*7d36db35SAvi Kivity unsigned long esp2; 29*7d36db35SAvi Kivity unsigned short ss2; 30*7d36db35SAvi Kivity unsigned short res4; 31*7d36db35SAvi Kivity unsigned long cr3; 32*7d36db35SAvi Kivity unsigned long eip; 33*7d36db35SAvi Kivity unsigned long eflags; 34*7d36db35SAvi Kivity unsigned long eax, ecx, edx, ebx, esp, ebp, esi, edi; 35*7d36db35SAvi Kivity unsigned short es; 36*7d36db35SAvi Kivity unsigned short res5; 37*7d36db35SAvi Kivity unsigned short cs; 38*7d36db35SAvi Kivity unsigned short res6; 39*7d36db35SAvi Kivity unsigned short ss; 40*7d36db35SAvi Kivity unsigned short res7; 41*7d36db35SAvi Kivity unsigned short ds; 42*7d36db35SAvi Kivity unsigned short res8; 43*7d36db35SAvi Kivity unsigned short fs; 44*7d36db35SAvi Kivity unsigned short res9; 45*7d36db35SAvi Kivity unsigned short gs; 46*7d36db35SAvi Kivity unsigned short res10; 47*7d36db35SAvi Kivity unsigned short ldt; 48*7d36db35SAvi Kivity unsigned short res11; 49*7d36db35SAvi Kivity unsigned short t:1; 50*7d36db35SAvi Kivity unsigned short res12:15; 51*7d36db35SAvi Kivity unsigned short iomap_base; 52*7d36db35SAvi Kivity }; 53*7d36db35SAvi Kivity 54*7d36db35SAvi Kivity static char main_stack[4096]; 55*7d36db35SAvi Kivity static char fault_stack[4096]; 56*7d36db35SAvi Kivity static struct tss32 main_tss; 57*7d36db35SAvi Kivity static struct tss32 fault_tss; 58*7d36db35SAvi Kivity 59*7d36db35SAvi Kivity static unsigned long long gdt[] __attribute__((aligned(16))) = { 60*7d36db35SAvi Kivity 0, 61*7d36db35SAvi Kivity 0x00cf9b000000ffffull, 62*7d36db35SAvi Kivity 0x00cf93000000ffffull, 63*7d36db35SAvi Kivity 0, 0, /* TSS segments */ 64*7d36db35SAvi Kivity 0, /* task return gate */ 65*7d36db35SAvi Kivity }; 66*7d36db35SAvi Kivity 67*7d36db35SAvi Kivity static unsigned long long gdtr; 68*7d36db35SAvi Kivity 69*7d36db35SAvi Kivity void fault_entry(void); 70*7d36db35SAvi Kivity 71*7d36db35SAvi Kivity static __attribute__((used, regparm(1))) void 72*7d36db35SAvi Kivity fault_handler(unsigned long error_code) 73*7d36db35SAvi Kivity { 74*7d36db35SAvi Kivity unsigned short *desc; 75*7d36db35SAvi Kivity 76*7d36db35SAvi Kivity printf("fault at %x:%x, prev task %x, error code %x\n", 77*7d36db35SAvi Kivity main_tss.cs, main_tss.eip, fault_tss.prev, error_code); 78*7d36db35SAvi Kivity 79*7d36db35SAvi Kivity main_tss.eip += 2; 80*7d36db35SAvi Kivity 81*7d36db35SAvi Kivity desc = (unsigned short *)&gdt[3]; 82*7d36db35SAvi Kivity desc[2] &= ~0x0200; 83*7d36db35SAvi Kivity 84*7d36db35SAvi Kivity desc = (unsigned short *)&gdt[5]; 85*7d36db35SAvi Kivity desc[0] = 0; 86*7d36db35SAvi Kivity desc[1] = fault_tss.prev; 87*7d36db35SAvi Kivity desc[2] = 0x8500; 88*7d36db35SAvi Kivity desc[3] = 0; 89*7d36db35SAvi Kivity } 90*7d36db35SAvi Kivity 91*7d36db35SAvi Kivity asm ( 92*7d36db35SAvi Kivity "fault_entry:\n" 93*7d36db35SAvi Kivity " mov (%esp),%eax\n" 94*7d36db35SAvi Kivity " call fault_handler\n" 95*7d36db35SAvi Kivity " jmp $0x28, $0\n" 96*7d36db35SAvi Kivity ); 97*7d36db35SAvi Kivity 98*7d36db35SAvi Kivity static void setup_tss(struct tss32 *tss, void *entry, 99*7d36db35SAvi Kivity void *stack_base, unsigned long stack_size) 100*7d36db35SAvi Kivity { 101*7d36db35SAvi Kivity unsigned long cr3; 102*7d36db35SAvi Kivity unsigned short cs, ds; 103*7d36db35SAvi Kivity 104*7d36db35SAvi Kivity asm ("mov %%cr3,%0" : "=r" (cr3)); 105*7d36db35SAvi Kivity asm ("mov %%cs,%0" : "=r" (cs)); 106*7d36db35SAvi Kivity asm ("mov %%ds,%0" : "=r" (ds)); 107*7d36db35SAvi Kivity 108*7d36db35SAvi Kivity tss->ss0 = tss->ss1 = tss->ss2 = tss->ss = ds; 109*7d36db35SAvi Kivity tss->esp0 = tss->esp1 = tss->esp2 = tss->esp = 110*7d36db35SAvi Kivity (unsigned long)stack_base + stack_size; 111*7d36db35SAvi Kivity tss->ds = tss->es = tss->fs = tss->gs = ds; 112*7d36db35SAvi Kivity tss->cs = cs; 113*7d36db35SAvi Kivity tss->eip = (unsigned long)entry; 114*7d36db35SAvi Kivity tss->cr3 = cr3; 115*7d36db35SAvi Kivity } 116*7d36db35SAvi Kivity 117*7d36db35SAvi Kivity static void setup_tss_desc(unsigned short tss_sel, struct tss32 *tss) 118*7d36db35SAvi Kivity { 119*7d36db35SAvi Kivity unsigned long addr = (unsigned long)tss; 120*7d36db35SAvi Kivity unsigned short *desc; 121*7d36db35SAvi Kivity 122*7d36db35SAvi Kivity desc = (unsigned short *)&gdt[tss_sel/8]; 123*7d36db35SAvi Kivity desc[0] = sizeof(*tss) - 1; 124*7d36db35SAvi Kivity desc[1] = addr; 125*7d36db35SAvi Kivity desc[2] = 0x8900 | ((addr & 0x00ff0000) >> 16); 126*7d36db35SAvi Kivity desc[3] = (addr & 0xff000000) >> 16; 127*7d36db35SAvi Kivity } 128*7d36db35SAvi Kivity 129*7d36db35SAvi Kivity static void set_intr_task(unsigned short tss_sel, int intr, struct tss32 *tss) 130*7d36db35SAvi Kivity { 131*7d36db35SAvi Kivity unsigned short *desc = (void *)(intr* sizeof(long) * 2); 132*7d36db35SAvi Kivity 133*7d36db35SAvi Kivity setup_tss_desc(tss_sel, tss); 134*7d36db35SAvi Kivity 135*7d36db35SAvi Kivity desc[0] = 0; 136*7d36db35SAvi Kivity desc[1] = tss_sel; 137*7d36db35SAvi Kivity desc[2] = 0x8500; 138*7d36db35SAvi Kivity desc[3] = 0; 139*7d36db35SAvi Kivity } 140*7d36db35SAvi Kivity 141*7d36db35SAvi Kivity int main(int ac, char **av) 142*7d36db35SAvi Kivity { 143*7d36db35SAvi Kivity const long invalid_segment = 0x1234; 144*7d36db35SAvi Kivity 145*7d36db35SAvi Kivity gdtr = ((unsigned long long)(unsigned long)&gdt << 16) | 146*7d36db35SAvi Kivity (sizeof(gdt) - 1); 147*7d36db35SAvi Kivity asm ("lgdt %0" : : "m" (gdtr)); 148*7d36db35SAvi Kivity 149*7d36db35SAvi Kivity setup_tss(&main_tss, 0, main_stack, sizeof(main_stack)); 150*7d36db35SAvi Kivity setup_tss_desc(FIRST_SPARE_SEL, &main_tss); 151*7d36db35SAvi Kivity asm ("ltr %0" : : "r" ((unsigned short)FIRST_SPARE_SEL)); 152*7d36db35SAvi Kivity 153*7d36db35SAvi Kivity setup_tss(&fault_tss, fault_entry, fault_stack, sizeof(fault_stack)); 154*7d36db35SAvi Kivity set_intr_task(FIRST_SPARE_SEL+8, 13, &fault_tss); 155*7d36db35SAvi Kivity 156*7d36db35SAvi Kivity asm ( 157*7d36db35SAvi Kivity "mov %0,%%es\n" 158*7d36db35SAvi Kivity : : "r" (invalid_segment) : "edi" 159*7d36db35SAvi Kivity ); 160*7d36db35SAvi Kivity 161*7d36db35SAvi Kivity printf("post fault\n"); 162*7d36db35SAvi Kivity 163*7d36db35SAvi Kivity return 0; 164*7d36db35SAvi Kivity } 165