/*[ c_xcptn.c LOCAL CHAR SccsID[]="@(#)c_xcptn.c 1.14 01/31/95"; Exception Handling Support. --------------------------- ]*/ #include #include #include #include StringH #include #include #include #include #include #include #include #include #include #include #include #include #include /* Allow print out of exceptions or disallow it. */ GLOBAL BOOL show_exceptions = FALSE; GLOBAL BOOL trap_exceptions = FALSE; LOCAL BOOL first_exception = TRUE; #define check_exception_env() \ { \ IMPORT char *host_getenv IPT1 (char *, name); \ if (first_exception) \ { \ char *env = host_getenv ("CCPU_SHOW_EXCEPTIONS"); \ if (env != NULL) \ { \ show_exceptions = TRUE; \ if (strcasecmp(env, "TRAP") == 0) \ trap_exceptions = TRUE; \ } \ } \ first_exception = FALSE; \ } IMPORT FILE *trace_file; IMPORT IBOOL took_absolute_toc; /* Intel interrupt(exception) numbers. */ #define I0_INT_NR 0 #define I1_INT_NR 1 #define I5_INT_NR 5 #define I6_INT_NR 6 #define I7_INT_NR 7 #define I16_INT_NR 16 #define DF_INT_NR 8 #define GP_INT_NR 13 #define NP_INT_NR 11 #define PF_INT_NR 14 #define SF_INT_NR 12 #define TS_INT_NR 10 #define NULL_ERROR_CODE (IU16)0 /* Intel IDT Error Code format. */ #define IDT_VECTOR_MASK 0xff #define IDT_VECTOR_SHIFT 3 #define IDT_INDICATOR_BIT 2 /* Interrupt/Fault Status. */ GLOBAL BOOL doing_contributory; GLOBAL BOOL doing_page_fault; GLOBAL BOOL doing_double_fault; GLOBAL BOOL doing_fault; /* true: FAULT, false: TRAP or ABORT */ GLOBAL ISM32 EXT; /* external/internal source */ GLOBAL IU32 CCPU_save_EIP; /* IP at start of instruction */ /* Prototype our internal functions. */ LOCAL VOID check_for_double_fault IPT1(IU16, xcode); LOCAL VOID check_for_shutdown IPT1(IU16, xcode); LOCAL VOID benign_exception IPT3( ISM32, nmbr, ISM32, source, IU16, xcode); LOCAL VOID contributory_exception IPT3( IU16, selector, ISM32, nmbr, IU16, xcode); LOCAL VOID contributory_idt_exception IPT3( IU16, vector, ISM32, nmbr, IU16, xcode); LOCAL char *faultstr IPT1(ISM32, nmbr ); /* ===================================================================== INTERNAL ROUTINES START HERE. ===================================================================== */ LOCAL char *faultstr IFN1(ISM32, nmbr ) { char *faulttable[] = { "DIV", "DBG", "NMI", "BPT", "OVF", "BND", "OPC", "NAV", "DF", "9", "TSS", "NP", "SF", "GP", "PF", "15", "FPE", "ALN" }; SAVED char buf[4]; if (nmbr > 16) { sprintf(buf, "%d", nmbr); return buf; } else return faulttable[nmbr]; } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Determine if things are so bad we need a double fault. */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ LOCAL VOID check_for_double_fault IFN1( IU16, xcode) { if ( doing_contributory || doing_page_fault ) DF(xcode); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Determine if things are so bad we need to close down. */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ LOCAL VOID check_for_shutdown IFN1(IU16, xcode) { if ( doing_double_fault ) { doing_contributory = FALSE; doing_page_fault = FALSE; doing_double_fault = FALSE; EXT = INTERNAL; /* force a reset - see schematic for AT motherboard */ c_cpu_reset(); #ifdef PIG save_last_xcptn_details("Exception:- Shutdown @%2d\n", xcode, 0, 0, 0, 0); ccpu_synch_count++; pig_cpu_action = CHECK_ALL; c_cpu_unsimulate(); #endif /* PIG */ /* then carry on */ c_cpu_continue(); /* DOES NOT RETURN */ } } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Handle Benign Exception */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ LOCAL VOID benign_exception IFN3( ISM32, nmbr, /* exception number */ ISM32, source, /* internal/external interrupt cause */ IU16, xcode /* insignia exception code */ ) { SET_EIP(CCPU_save_EIP); #ifdef NTVDM { extern BOOL host_exint_hook IPT2(IS32, exp_no, IS32, error_code); if(GET_PE() && host_exint_hook((IS32) nmbr, NULL_ERROR_CODE)) c_cpu_continue(); /* DOES NOT RETURN */ } #endif /* Set default mode up */ SET_OPERAND_SIZE(GET_SR_AR_X(CS_REG)); SET_ADDRESS_SIZE(GET_SR_AR_X(CS_REG)); SET_POP_DISP(0); EXT = source; check_exception_env(); #ifdef PIG save_last_xcptn_details("Exception:- #%s-%d @%2d \n", (IUH)faultstr(nmbr), nmbr, xcode, 0, 0); #endif /* PIG */ if (show_exceptions){ fprintf(trace_file, "(%04x:%08x)Exception:- %d.\n", GET_CS_SELECTOR(), GET_EIP(), nmbr); if (trap_exceptions) force_yoda(); } took_absolute_toc = TRUE; do_intrupt((IU16)nmbr, FALSE, FALSE, NULL_ERROR_CODE); c_cpu_continue(); /* DOES NOT RETURN */ } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Handle Contributory Exception */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ LOCAL VOID contributory_exception IFN3( IU16, selector, /* failing selector */ ISM32, nmbr, /* exception number */ IU16, xcode /* insignia exception code */ ) { IU16 error_code; /* check if exception caused by external caller */ check_interface_active(nmbr); check_for_shutdown(xcode); check_for_double_fault(xcode); doing_contributory = TRUE; error_code = (selector & 0xfffc) | EXT; SET_EIP(CCPU_save_EIP); #ifdef NTVDM { extern BOOL host_exint_hook IPT2(IS32, exp_no, IS32, error_code); if(GET_PE() && host_exint_hook((IS32) nmbr, (IS32)error_code)) doing_contributory = FALSE; c_cpu_continue(); /* DOES NOT RETURN */ } #endif /* Set default mode up */ SET_OPERAND_SIZE(GET_SR_AR_X(CS_REG)); SET_ADDRESS_SIZE(GET_SR_AR_X(CS_REG)); SET_POP_DISP(0); EXT = INTERNAL; check_exception_env(); #ifdef PIG save_last_xcptn_details("Exception:- #%s-%d(%04x) @%2d\n", (IUH)faultstr(nmbr), nmbr, error_code, xcode, 0); #endif /* PIG */ if (show_exceptions){ fprintf(trace_file, "(%04x:%08x)Exception:- %d(%04x).\n", GET_CS_SELECTOR(), GET_EIP(), nmbr, error_code); if (trap_exceptions) force_yoda(); } took_absolute_toc = TRUE; do_intrupt((IU16)nmbr, FALSE, TRUE, error_code); c_cpu_continue(); /* DOES NOT RETURN */ } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Handle Contributory Exception (Via IDT). */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ LOCAL VOID contributory_idt_exception IFN3( IU16, vector, /* failing interrupt vector */ ISM32, nmbr, /* exception number */ IU16, xcode /* insignia exception code */ ) { IU16 error_code; /* check if exception caused by external caller */ check_interface_active(nmbr); check_for_shutdown(xcode); check_for_double_fault(xcode); doing_contributory = TRUE; error_code = ((vector & IDT_VECTOR_MASK) << IDT_VECTOR_SHIFT) | IDT_INDICATOR_BIT | EXT; SET_EIP(CCPU_save_EIP); #ifdef NTVDM { extern BOOL host_exint_hook IPT2(IS32, exp_no, IS32, error_code); if(GET_PE() && host_exint_hook((IS32) nmbr, (IS32)error_code)) doing_contributory = FALSE; c_cpu_continue(); /* DOES NOT RETURN */ } #endif /* Set default mode up */ SET_OPERAND_SIZE(GET_SR_AR_X(CS_REG)); SET_ADDRESS_SIZE(GET_SR_AR_X(CS_REG)); SET_POP_DISP(0); EXT = INTERNAL; check_exception_env(); #ifdef PIG save_last_xcptn_details("Exception:- %s-%d(%04x) @%2d\n", (IUH)faultstr(nmbr), nmbr, error_code, xcode, 0); #endif /* PIG */ if (show_exceptions){ if ( GET_IDT_LIMIT() != 0 ){ fprintf(trace_file, "(%04x:%08x)Exception:- %d(%04x).\n", GET_CS_SELECTOR(), GET_EIP(), nmbr, error_code); if (trap_exceptions) force_yoda(); } } took_absolute_toc = TRUE; do_intrupt((IU16)nmbr, FALSE, TRUE, error_code); c_cpu_continue(); /* DOES NOT RETURN */ } /* ===================================================================== EXTERNAL ROUTINES START HERE. ===================================================================== */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Interrupt Table Too Small/Double Fault Exception. */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ GLOBAL VOID DF IFN1( IU16, xcode /* insignia exception code */ ) { doing_fault = FALSE; if ( GET_PE() == 1 ) { check_for_shutdown(xcode); doing_double_fault = TRUE; } SET_EIP(CCPU_save_EIP); #ifdef NTVDM { extern BOOL host_exint_hook IPT2(IS32, exp_no, IS32, error_code); if(GET_PE() && host_exint_hook((IS32) DF_INT_NR, (IS32)NULL_ERROR_CODE)) doing_double_fault = FALSE; c_cpu_continue(); /* DOES NOT RETURN */ } #endif /* Set default mode up */ SET_OPERAND_SIZE(GET_SR_AR_X(CS_REG)); SET_ADDRESS_SIZE(GET_SR_AR_X(CS_REG)); SET_POP_DISP(0); EXT = INTERNAL; check_exception_env(); #ifdef PIG save_last_xcptn_details("Exception:- #DF-8 @%2d\n", xcode, 0, 0, 0, 0); #endif /* PIG */ if (show_exceptions){ if ( GET_IDT_LIMIT() != 0 ){ fprintf(trace_file, "(%04x:%08x)Exception:- %d.\n", GET_CS_SELECTOR(), GET_EIP(), DF_INT_NR); if (trap_exceptions) force_yoda(); } } took_absolute_toc = TRUE; do_intrupt((IU16)DF_INT_NR, FALSE, TRUE, NULL_ERROR_CODE); c_cpu_continue(); /* DOES NOT RETURN */ } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* General Protection Exception. */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ GLOBAL VOID GP IFN2( IU16, selector, IU16, xcode) { doing_fault = TRUE; contributory_exception(selector, GP_INT_NR, xcode); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* General Protection Exception. (Via IDT) */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ GLOBAL VOID GP_INT IFN2( IU16, vector, IU16, xcode) { doing_fault = TRUE; contributory_idt_exception(vector, GP_INT_NR, xcode); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Divide Error Exception. */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ GLOBAL VOID Int0 IFN0 () { doing_fault = TRUE; if ( GET_PE() == 1 ) { doing_contributory = TRUE; } SET_EIP(CCPU_save_EIP); #ifdef NTVDM { extern BOOL host_exint_hook IPT2(IS32, exp_no, IS32, error_code); if(GET_PE() && host_exint_hook((IS32) I0_INT_NR, (IS32)NULL_ERROR_CODE)) doing_fault = FALSE; doing_contributory = FALSE; c_cpu_continue(); /* DOES NOT RETURN */ } #endif /* Set default mode up */ SET_OPERAND_SIZE(GET_SR_AR_X(CS_REG)); SET_ADDRESS_SIZE(GET_SR_AR_X(CS_REG)); SET_POP_DISP(0); EXT = INTERNAL; check_exception_env(); #ifdef PIG save_last_xcptn_details("Exception:- #DIV-0\n", 0, 0, 0, 0, 0); #endif /* PIG */ if (show_exceptions){ fprintf(trace_file, "(%04x:%08x)Exception:- %d.\n", GET_CS_SELECTOR(), GET_EIP(), I0_INT_NR); if (trap_exceptions) force_yoda(); } took_absolute_toc = TRUE; do_intrupt((IU16)I0_INT_NR, FALSE, FALSE, NULL_ERROR_CODE); c_cpu_continue(); /* DOES NOT RETURN */ } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Single Step Exception. (FAULT) */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ GLOBAL VOID Int1_f() { doing_fault = TRUE; benign_exception(I1_INT_NR, EXTERNAL, -1); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Single Step Exception. (TRAP) */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ GLOBAL VOID Int1_t() { doing_fault = FALSE; benign_exception(I1_INT_NR, EXTERNAL, -1); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Bounds Check Exception. */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ GLOBAL VOID Int5() { doing_fault = TRUE; benign_exception(I5_INT_NR, INTERNAL, -1); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Invalid Opcode Exception. */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ GLOBAL VOID Int6() { doing_fault = TRUE; benign_exception(I6_INT_NR, INTERNAL, -1); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* NPX Not Available Exception. */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ GLOBAL VOID Int7() { doing_fault = TRUE; benign_exception(I7_INT_NR, INTERNAL, -1); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* NPX Error Exception. */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ GLOBAL VOID Int16() { doing_fault = TRUE; benign_exception(I16_INT_NR, EXTERNAL, -1); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Not Present Exception. */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ GLOBAL VOID NP IFN2( IU16, selector, IU16, xcode) { doing_fault = TRUE; contributory_exception(selector, NP_INT_NR, xcode); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Not Present Exception. (Via IDT) */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ GLOBAL VOID NP_INT IFN2( IU16, vector, IU16, xcode ) { doing_fault = TRUE; contributory_idt_exception(vector, NP_INT_NR, xcode); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Page Fault Exception. */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ GLOBAL VOID PF IFN2( IU16, page_error, /* correctly formatted page fault error code */ IU16, xcode ) { /* check if exception caused by external caller */ check_interface_active(PF_INT_NR); doing_fault = TRUE; check_for_shutdown(xcode); /* Check for double page fault */ if ( doing_page_fault ) DF(xcode); doing_page_fault = TRUE; SET_EIP(CCPU_save_EIP); #ifdef NTVDM { extern BOOL host_exint_hook IPT2(IS32, exp_no, IS32, error_code); if(GET_PE() && host_exint_hook((IS32) PF_INT_NR, (IS32)page_error)) doing_fault = FALSE; doing_page_fault = FALSE; c_cpu_continue(); /* DOES NOT RETURN */ } #endif /* Set default mode up */ SET_OPERAND_SIZE(GET_SR_AR_X(CS_REG)); SET_ADDRESS_SIZE(GET_SR_AR_X(CS_REG)); SET_POP_DISP(0); check_exception_env(); #ifdef PIG save_last_xcptn_details("Exception:- #PF-14(%04x) CR2=%08x @%2d\n", page_error, GET_CR(CR_PFLA), xcode, 0, 0); #endif /* PIG */ if (show_exceptions){ fprintf(trace_file, "(%04x:%08x)Exception:- %d(%04x) CR2=%08x.\n", GET_CS_SELECTOR(), GET_EIP(), PF_INT_NR, page_error, GET_CR(CR_PFLA)); if (trap_exceptions) force_yoda(); } took_absolute_toc = TRUE; do_intrupt((IU16)PF_INT_NR, FALSE, TRUE, page_error); c_cpu_continue(); /* DOES NOT RETURN */ } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Stack Fault Exception. */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ GLOBAL VOID SF IFN2( IU16, selector, IU16, xcode ) { doing_fault = TRUE; contributory_exception(selector, SF_INT_NR, xcode); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Task Switch Exception. */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ GLOBAL VOID TS IFN2( IU16, selector, IU16, xcode ) { doing_fault = TRUE; contributory_exception(selector, TS_INT_NR, xcode); }