/********************************************************************* * * Copyright (C) 2002-2003, 2007-2010, Karlsruhe University * * File path: arch/x86/x32/trapgate.h * Description: defines macros for implementation of trap and * interrupt gates in C * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: trapgate.h,v 1.8 2003/09/24 19:04:27 skoglund Exp $ * ********************************************************************/ #ifndef __ARCH__X86__X32__TRAPGATE_H__ #define __ARCH__X86__X32__TRAPGATE_H__ class x86_exceptionframe_t; class x86_exceptionregs_t { public: static const word_t num_regs = 17; enum reg_e { esreg = 1, dsreg = 2, Dreg = 3, Sreg = 4, Breg = 5, breg = 7, dreg = 8, creg = 9, areg = 10, ereg = 11, ipreg = 12, csreg = 13, freg = 14, spreg = 15, ssreg = 16, }; union { struct { u32_t reason; /* 0 */ u32_t es; /* 1 */ u32_t ds; /* 2 */ u32_t edi; /* 3 */ u32_t esi; /* 4 */ u32_t ebp; /* 5 */ u32_t __esp; u32_t ebx; /* 7 */ u32_t edx; /* 8 */ u32_t ecx; /* 9 */ u32_t eax; /* 10 */ /* default trapgate frame */ u32_t error; /* 11 */ u32_t eip; /* 12 */ u32_t cs; /* 13 */ u32_t eflags; /* 14 */ u32_t esp; /* 15 */ u32_t ss; /* 16 */ }; word_t regs[num_regs]; }; #if defined(CONFIG_DEBUG) static const word_t num_dbgregs = 12; #endif }; /* * If KEEP_LAST_BRANCHES is enabled we should clear the LBR flag prior * to handling the exception so as to avoid overwriting the last * branch records by regular kernel code. */ #if defined(CONFIG_X86_KEEP_LAST_BRANCHES) #define clr_dbgctl_lbr() \ "mov $0x1d9, %%ecx \n"\ "rdmsr \n"\ "andl $0xfffffffe, %%eax \n"\ "wrmsr \n" #define set_dbgctl_lbr() \ "mov $0x1d9, %%ecx \n"\ "rdmsr \n"\ "orl $0x1, %%eax \n"\ "wrmsr \n" #else #define clr_dbgctl_lbr() #define set_dbgctl_lbr() #endif #if defined(CONFIG_X86_SMALL_SPACES) #define set_kds(reg) \ "mov $" MKSTR(X86_KDS) ", %%" #reg " \n" \ "mov %%" #reg ", %%ds \n" #else #define set_kds(reg) #endif #if defined(X86_EXC_KDB) /* js: in rare cases, we might get a NMI (or breakpoint exception) just * after sys_ipc has been invoked, but _before_ esp has been set to tss.esp0 * in that case, we need to switch stacks manually and preserve the * processor-saved frame. We make sure that, before tss there is enough scratch * space to cover EFLAGS, CS, and EIP saved by the processor; this way, we can * get along without having to establish a interrupt task xgate for KDB */ #define kdb_check_stack() \ "push %%ebp \n" \ "lea (tss - 12), %%ebp \n" \ "cmpl %%esp, %%ebp \n" \ "pop %%ebp \n" \ "jne 1f \n" \ "addl $12, %%esp \n" \ "movl (%%esp), %%esp \n" \ "subl $12, %%esp \n" \ "push %%ebp \n" \ "mov (tss ), %%ebp \n" \ "mov %%ebp, 12(%%esp) \n" \ "mov (tss - 4), %%ebp \n" \ "mov %%ebp, 8(%%esp) \n" \ "mov (tss - 8), %%ebp \n" \ "add $3, %%ebp \n" \ "mov %%ebp, 4(%%esp) \n" \ "pop %%ebp \n" \ "1: \n" #else #define kdb_check_stack() #endif /** * X86_EXCWITH_ERRORCODE: allows C implementation of * exception handlers and trap/interrupt gates with error * code. * * Usage: X86_EXCWITH_ERRORCODE(exc_gp) */ #define X86_EXCWITH_ERRORCODE(name, reason) \ extern "C" void name (void); \ static void name##handler(x86_exceptionframe_t * frame); \ void name##_wrapper() \ { \ u32_t *handler = (u32_t*)name##handler; \ __asm__ ( \ ".global "#name " \n" \ "\t.type "#name",@function \n" \ #name": \n" \ "pusha \n" \ "push %%ds \n" \ "push %%es \n" \ "push %1 \n" \ "push %%esp \n" \ set_kds (eax) \ clr_dbgctl_lbr () \ "call %0 \n" \ set_dbgctl_lbr () \ "addl $8, %%esp \n" \ "popl %%es \n" \ "popl %%ds \n" \ "popa \n" \ "addl $4, %%esp \n" \ "iret \n" \ : \ : "m"(*handler), "i"(reason) \ ); \ } \ static void name##handler(x86_exceptionframe_t * frame) #define X86_EXCNO_ERRORCODE(name, reason) \ extern "C" void name (void); \ static void name##handler(x86_exceptionframe_t * frame); \ void name##_wrapper() \ { \ u32_t *handler = (u32_t*)name##handler; \ __asm__ ( \ ".global "#name " \n" \ "\t.type "#name",@function \n" \ #name": \n" \ kdb_check_stack() \ "subl $4, %%esp \n" \ "pusha \n" \ "push %%ds \n" \ "push %%es \n" \ "push %1 \n" \ "push %%esp \n" \ set_kds (eax) \ clr_dbgctl_lbr () \ "call %0 \n" \ set_dbgctl_lbr () \ "addl $8, %%esp \n" \ "popl %%es \n" \ "popl %%ds \n" \ "popa \n" \ "addl $4, %%esp \n" \ "iret \n" \ : \ : "m"(*handler), "i"(reason) \ ); \ } \ static void name##handler(x86_exceptionframe_t * frame) #endif /* !__ARCH__X86__X32__TRAPGATE_H__ */