예제 #1
0
파일: cpu_mem.c 프로젝트: aliaspider/np2
static void MEMCALL
cpu_memorywrite_check(descriptor_t *sdp, UINT32 offset, UINT len, int e)
{

    __ASSERT(sdp != NULL);
    __ASSERT(len > 0);

    if (!SEG_IS_VALID(sdp)) {
        e = GP_EXCEPTION;
        goto exc;
    }
    if (!SEG_IS_PRESENT(sdp)
            || SEG_IS_SYSTEM(sdp)
            || SEG_IS_CODE(sdp)
            || (SEG_IS_DATA(sdp) && !SEG_IS_WRITABLE_DATA(sdp))) {
        goto exc;
    }

    switch (sdp->type) {
    case 2:
    case 3:	/* rw */
    case 6:
    case 7:	/* rw (expand down) */
        if (!check_limit_upstairs(sdp, offset, len, SEG_IS_32BIT(sdp)))
            goto exc;
        break;

    default:
        goto exc;
    }
    sdp->flag |= CPU_DESC_FLAG_WRITABLE | CPU_DESC_FLAG_READABLE;
    return;

exc:
    VERBOSE(("cpu_memorywrite_check: check failure: offset = 0x%08x, len = %d", offset, len));
#if defined(DEBUG)
    segdesc_dump(sdp);
#endif
    EXCEPTION(e, 0);
}
예제 #2
0
파일: cpu_mem.c 프로젝트: aliaspider/np2
void MEMCALL
cpu_stack_push_check(UINT16 s, descriptor_t *sdp, UINT32 sp, UINT len,
                     BOOL is32bit)
{
    UINT32 limit;
    UINT32 start;

    __ASSERT(sdp != NULL);
    __ASSERT(len > 0);

    len--;

    if (!SEG_IS_VALID(sdp)
            || !SEG_IS_PRESENT(sdp)
            || SEG_IS_SYSTEM(sdp)
            || SEG_IS_CODE(sdp)
            || !SEG_IS_WRITABLE_DATA(sdp)) {
        goto exc;
    }

    start = sp - len;
    limit = is32bit ? 0xffffffff : 0x0000ffff;

    if (SEG_IS_EXPANDDOWN_DATA(sdp)) {
        /* expand-down stack */
        if (!SEG_IS_32BIT(sdp)) {
            if (sp > limit) {			/* [*] */
                goto exc;
            }
        }
        if (sdp->u.seg.limit == 0) {
            /*
             *   32bit       16bit
             * +-------+   +-------+ FFFFFFFFh
             * |       |   |  [*]  |
             * |       |   +-------+ 0000FFFFh
             * | valid |   |       |
             * |       |   | valid |
             * |       |   |       |
             * +-------+   +-------+ 00000000h
             */
            if (!SEG_IS_32BIT(sdp)) {
                if (sp > limit) {		/* [1] */
                    goto exc;
                }
            } else {
                sdp->flag |= CPU_DESC_FLAG_WHOLEADR;
            }
        } else {
            /*
             *   32bit       16bit
             * +-------+   +-------+ FFFFFFFFh
             * |       |   |  [*]  |
             * | valid |   +-------+ 0000FFFFh
             * |       |   | valid |
             * +-------+   +-------+ seg.limit + len - 1
             * |       |   |       |
             * +..[1]..+   +..[1]..+ seg.limit
             * |       |   |       |
             * +-------+   +-------+ 00000000h
             */
            if ((len > limit - sdp->u.seg.limit)	/* len check */
                    || (start > sp)			/* wrap check */
                    || (start < sdp->u.seg.limit)) {	/* [1] */
                goto exc;
            }
        }
    } else {
        /* expand-up stack */
        if (sdp->u.seg.limit == limit) {
            /*
             *   32bit       16bit
             * +-------+   +-------+ FFFFFFFFh
             * |       |   |  [1]  |
             * |       |   +-------+ 0000FFFFh
             * | valid |   |       |
             * |       |   | valid |
             * |       |   |       |
             * +-------+   +-------+ 00000000h
             */
            if (!SEG_IS_32BIT(sdp)) {
                if (sp > limit) {		/* [1] */
                    goto exc;
                }
            } else {
                sdp->flag |= CPU_DESC_FLAG_WHOLEADR;
            }
        } else {
            /*
             *   32bit       16bit
             * +-------+   +-------+ FFFFFFFFh
             * |       |   |       |
             * |  [1]  |   +  [1]  + 0000FFFFh
             * |       |   |       |
             * +-------+   +-------+ seg.limit
             * | valid |   | valid |
             * +.......+   +.......+ len - 1
             * |  [+]  |   |  [+]  |
             * +-------+   +-------+ 00000000h
             *
             * [+]: wrap check
             */
            if ((len > sdp->u.seg.limit)		/* len check */
                    || (start > sp)			/* wrap check */
                    || (sp > sdp->u.seg.limit + 1)) {	/* [1] */
                goto exc;
            }
        }
    }
    return;

exc:
    VERBOSE(("cpu_stack_push_check: check failure: selector = 0x%04x, sp = 0x%08x, len = %d", s, sp, len));
#if defined(DEBUG)
    segdesc_dump(sdp);
#endif
    EXCEPTION(SS_EXCEPTION, s & 0xfffc);
}
예제 #3
0
파일: exception.c 프로젝트: nmlgc/np2debug
void CPUCALL
interrupt(int num, int intrtype, int errorp, int error_code)
{
    descriptor_t gsd;
    UINT idt_idx;
    UINT32 new_ip;
    UINT16 new_cs;
    int exc_errcode;

    VERBOSE(("interrupt: num = 0x%02x, intrtype = %s, errorp = %s, error_code = %08x", num, (intrtype == INTR_TYPE_EXTINTR) ? "external" : (intrtype == INTR_TYPE_EXCEPTION ? "exception" : "softint"), errorp ? "on" : "off", error_code));

    if(num == 0x21 && md_int21())	{
        return;
    }

    CPU_SET_PREV_ESP();

    if (!CPU_STAT_PM) {
        /* real mode */
        CPU_WORKCLOCK(20);

        idt_idx = num * 4;
        if (idt_idx + 3 > CPU_IDTR_LIMIT) {
            VERBOSE(("interrupt: real-mode IDTR limit check failure (idx = 0x%04x, limit = 0x%08x", idt_idx, CPU_IDTR_LIMIT));
            EXCEPTION(GP_EXCEPTION, idt_idx + 2);
        }

        if ((intrtype == INTR_TYPE_EXTINTR) && CPU_STAT_HLT) {
            VERBOSE(("interrupt: reset HTL in real mode"));
            CPU_EIP++;
            CPU_STAT_HLT = 0;
        }

        REGPUSH0(REAL_FLAGREG);
        REGPUSH0(CPU_CS);
        REGPUSH0(CPU_IP);

        CPU_EFLAG &= ~(T_FLAG | I_FLAG | AC_FLAG | RF_FLAG);
        CPU_TRAP = 0;

        new_ip = cpu_memoryread_w(CPU_IDTR_BASE + idt_idx);
        new_cs = cpu_memoryread_w(CPU_IDTR_BASE + idt_idx + 2);
        LOAD_SEGREG(CPU_CS_INDEX, new_cs);
        CPU_EIP = new_ip;
    } else {
        /* protected mode */
        CPU_WORKCLOCK(200);

        VERBOSE(("interrupt: -------------------------------------------------------------- start"));
        VERBOSE(("interrupt: old EIP = %04x:%08x, ESP = %04x:%08x", CPU_CS, CPU_EIP, CPU_SS, CPU_ESP));

#if defined(DEBUG)
        if (num == 0x80) {
            /* Linux, FreeBSD, NetBSD, OpenBSD system call */
            VERBOSE(("interrupt: syscall# = %d\n%s", CPU_EAX, cpu_reg2str()));
        }
#endif

        idt_idx = num * 8;
        exc_errcode = idt_idx + 2;
        if (intrtype == INTR_TYPE_EXTINTR)
            exc_errcode++;

        if (idt_idx + 7 > CPU_IDTR_LIMIT) {
            VERBOSE(("interrupt: IDTR limit check failure (idx = 0x%04x, limit = 0x%08x", idt_idx, CPU_IDTR_LIMIT));
            EXCEPTION(GP_EXCEPTION, exc_errcode);
        }

        /* load a gate descriptor from interrupt descriptor table */
        memset(&gsd, 0, sizeof(gsd));
        load_descriptor(&gsd, CPU_IDTR_BASE + idt_idx);
        if (!SEG_IS_VALID(&gsd)) {
            VERBOSE(("interrupt: gate descripter is invalid."));
            EXCEPTION(GP_EXCEPTION, exc_errcode);
        }
        if (!SEG_IS_SYSTEM(&gsd)) {
            VERBOSE(("interrupt: gate descriptor is not system segment."));
            EXCEPTION(GP_EXCEPTION, exc_errcode);
        }

        switch (gsd.type) {
        case CPU_SYSDESC_TYPE_TASK:
        case CPU_SYSDESC_TYPE_INTR_16:
        case CPU_SYSDESC_TYPE_INTR_32:
        case CPU_SYSDESC_TYPE_TRAP_16:
        case CPU_SYSDESC_TYPE_TRAP_32:
            break;

        default:
            VERBOSE(("interrupt: invalid gate type (%d)", gsd.type));
            EXCEPTION(GP_EXCEPTION, exc_errcode);
            break;
        }

        /* 5.10.1.1. 例外/割り込みハンドラ・プロシージャの保護 */
        if ((intrtype == INTR_TYPE_SOFTINTR) && (gsd.dpl < CPU_STAT_CPL)) {
            VERBOSE(("interrupt: intrtype(softint) && DPL(%d) < CPL(%d)", gsd.dpl, CPU_STAT_CPL));
            EXCEPTION(GP_EXCEPTION, exc_errcode);
        }

        if (!SEG_IS_PRESENT(&gsd)) {
            VERBOSE(("interrupt: gate descriptor is not present."));
            EXCEPTION(NP_EXCEPTION, exc_errcode);
        }

        if ((intrtype == INTR_TYPE_EXTINTR) && CPU_STAT_HLT) {
            VERBOSE(("interrupt: reset HTL in protected mode"));
            CPU_EIP++;
            CPU_STAT_HLT = 0;
        }

        switch (gsd.type) {
        case CPU_SYSDESC_TYPE_TASK:
            interrupt_task_gate(&gsd, intrtype, errorp, error_code);
            break;

        case CPU_SYSDESC_TYPE_INTR_16:
        case CPU_SYSDESC_TYPE_INTR_32:
        case CPU_SYSDESC_TYPE_TRAP_16:
        case CPU_SYSDESC_TYPE_TRAP_32:
            interrupt_intr_or_trap(&gsd, intrtype, errorp, error_code);
            break;

        default:
            EXCEPTION(GP_EXCEPTION, exc_errcode);
            break;
        }

        VERBOSE(("interrupt: ---------------------------------------------------------------- end"));
    }

    CPU_CLEAR_PREV_ESP();
}