/* * Copyright (c) 2016 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #ifndef X86_EXCEPTION_H #define X86_EXCEPTION_H #ifndef _ASMLANGUAGE #include #define _EXCEPTION_INTLIST(vector) \ ".pushsection .gnu.linkonce.intList.exc_" #vector "\n\t" \ ".long 1f\n\t" /* ISR_LIST.fnc */ \ ".long -1\n\t" /* ISR_LIST.irq */ \ ".long -1\n\t" /* ISR_LIST.priority */ \ ".long " STRINGIFY(vector) "\n\t" /* ISR_LIST.vec */ \ ".long 0\n\t" /* ISR_LIST.dpl */ \ ".long 0\n\t" /* ISR_LIST.tss */ \ ".popsection\n\t" \ /* Extra preprocessor indirection to ensure arguments get expanded before * concatenation takes place */ #define __EXCEPTION_STUB_NAME(handler, vec) \ _ ## handler ## _vector_ ## vec ## _stub #define _EXCEPTION_STUB_NAME(handler, vec) \ __EXCEPTION_STUB_NAME(handler, vec) \ /* Unfortunately, GCC extended asm doesn't work at toplevel so we need * to stringify stuff. * * What we are doing here is generating entires in the .intList section * and also the assembly language stubs for the exception. We use * .gnu.linkonce section prefix so that the linker only includes the * first one of these it encounters for a particular vector. In this * way it's easy for applications or drivers to install custom exception * handlers without having to #ifdef out previous instances such as in * arch/x86/core/fatal.c */ #define __EXCEPTION_CONNECT(handler, vector, codepush) \ __asm__ ( \ _EXCEPTION_INTLIST(vector) \ ".pushsection .gnu.linkonce.t.exc_" STRINGIFY(vector) \ "_stub, \"ax\"\n\t" \ ".global " STRINGIFY(_EXCEPTION_STUB_NAME(handler, vector)) "\n\t" \ STRINGIFY(_EXCEPTION_STUB_NAME(handler, vector)) ":\n\t" \ "1:\n\t" \ codepush \ "push $" STRINGIFY(handler) "\n\t" \ "jmp _exception_enter\n\t" \ ".popsection\n\t" \ ) /** * @brief Connect an exception handler that doesn't expect error code * * Assign an exception handler to a particular vector in the IDT. * * @param handler A handler function of the prototype * void handler(const NANO_ESF *esf) * @param vector Vector index in the IDT */ #define _EXCEPTION_CONNECT_NOCODE(handler, vector) \ __EXCEPTION_CONNECT(handler, vector, "push $0\n\t") /** * @brief Connect an exception handler that does expect error code * * Assign an exception handler to a particular vector in the IDT. * The error code will be accessible in esf->errorCode * * @param handler A handler function of the prototype * void handler(const NANO_ESF *esf) * @param vector Vector index in the IDT */ #define _EXCEPTION_CONNECT_CODE(handler, vector) \ __EXCEPTION_CONNECT(handler, vector, "") #endif /* _ASMLANGUAGE */ #endif /* X86_EXCEPTION_H */