⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 except.s

📁 WinCE5.0部分核心源码
💻 S
📖 第 1 页 / 共 5 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
//------------------------------------------------------------------------------
//      TITLE("Interrupt and Exception Processing")
//------------------------------------------------------------------------------
//
//
// Module Name:
//
//    except.s
//
// Abstract:
//
//    This module implements the code necessary to field and process MIPS
//    interrupt and exception conditions.
//
//    WARNING: This module executes in KSEG0 and, in general, cannot
//       tolerate a TLB Miss. Registers k0 and k1 are used during initial
//   interrupt and exception processing, and therefore, extreme care must
//   be exercised when modifying this module.
//
//------------------------------------------------------------------------------

#include "ksmips.h"
#include "nkintr.h"
#include "kpage.h"
#include "mem_mips.h"
#include "psyscall.h"

#define VR5432_BP_BUG 1

// must match the value in kernel.h
#define SECURESTK_RESERVE       (32 + 4*REG_SIZE)      // SIZE_PRETLS + 4 * REG_SIZE
#define MAX_PSL_ARGS            (14 * REG_SIZE)        // 14 max PSL args

#define CALLEE_SAVED_REGS       (10 * REG_SIZE)        // (s0 - s8, gp)

#define PERFORMCALLBACK         -113    // MUST be -PerformCallback Win32Methods in kwin32.c 
                                        // 113 == -(APISet 0, method 113)
#define RAISEEXCEPTION          -114    // MUST be -RaiseException Win32Methods in kwin32.c
#define KERN_TRUST_FULL         2

#if defined(VR5432_BP_BUG)
    //
    // An external routine calling into this code is at risk for
        // this bug if there is a conditional branch close to the call
        // and interrupts are enabled at the time of the branch
        //
    // MAKE SURE THE LABEL 199 IS NOT USED IN THIS FILE
#define CP0_STOP_PREFETCH(inst, parm1, parm2, tempreg)  \
        la      tempreg, 199f;                           \
        j       tempreg;                                \
        nop;                                            \
199:                                                     \
        inst    parm1, parm2;                              
#else
#define CP0_STOP_PREFETCH(inst, parm1, parm2, tempreg) \
        inst    parm1, parm2;                              
#endif
        
        .text
        .globl  MD_CBRtn
        .globl  PtrCurMSec

PtrCurMSec: 
        .word   AddrCurMSec

PosTable:
        .byte 0,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1
        .byte 6,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1
        .byte 7,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1
        .byte 6,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1
        .byte 8,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1
        .byte 6,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1
        .byte 7,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1
        .byte 6,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
LEAF_ENTRY (GetHighPos)
        .set noreorder
        
        addi    t0, zero, -1
        andi    t1, a0, 0xff
        lb      v0, PosTable(t1)
        bne     zero, v0, res
        srl     a0, a0, 8
        
        addi    t0, t0, 8
        andi    t1, a0, 0xff
        lb      v0, PosTable(t1)
        bne     zero, v0, res
        srl     a0, a0, 8
        
        addi    t0, t0, 8
        andi    t1, a0, 0xff
        lb      v0, PosTable(t1)
        bne     zero, v0, res
        srl     a0, a0, 8
        
        addi    t0, t0, 8
        andi    t1, a0, 0xff
        lb      v0, PosTable(t1)
        bne     zero, v0, res
        nop
        
        addi    v0, v0, 9
res:
        j       ra
        add     v0, v0, t0
        
        .end GetHighPos


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
LEAF_ENTRY(INTERRUPTS_ON)
        .set noreorder
        
        lw      t0, BasePSR
        nop
        or      t0, 1
        j       ra
        mtc0    t0, psr
        
        .end INTERRUPTS_ON

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
LEAF_ENTRY(INTERRUPTS_OFF)
        .set noreorder
        
        CP0_STOP_PREFETCH(mtc0, zero, psr, t0);
        nop         // 3 cycle delay
        j       ra
        nop
        
        .end INTERRUPTS_OFF


//------------------------------------------------------------------------------
// Enable interrupts if input parameter is non-zero (previously had interrupts on)
//------------------------------------------------------------------------------
LEAF_ENTRY(INTERRUPTS_ENABLE)
        .set noreorder

        CP0_STOP_PREFETCH(mfc0, v0, psr, t0);

        sltu    a0, zero, a0            // (a0) = 1 if non-zero, 0 otherwise
        move    t0, v0                  // (t0) = current PSR

        // clear IE bit of t0
        srl     t0, 1
        sll     t0, 1

        // update IE bit of t0 based on the argument
        add     t0, t0, a0

        // update PSR
        mtc0    t0, psr

        // return
        j       ra
        and     v0, v0, 1               // (v0) = 1 if interrupt was enabled, 0 otherwise. (delay slot)

        .end INTERRUPTS_ENABLE

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
        NESTED_ENTRY(NKCallIntChain, 0, zero)
        subu    sp, sp, 5*REG_SIZE              // reserve space on stack, 4 extra register save area per C calling convention
        S_REG   ra, 4*REG_SIZE(sp)              // save return address
        PROLOGUE_END
        
        jal     NKCallIntChainWrapped
        nop

        L_REG   ra, 4*REG_SIZE(sp)              // restore return address
        
        j       ra                              // return
        addu    sp, sp, 5*REG_SIZE              // (delay slot) reclaim stack
        .end NKCallIntChain

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
        LEAF_ENTRY (NKIsSysIntrValid)

        .set    noreorder
        .set    noat
        
        subu    a0, SYSINTR_DEVICES             // (a0) = idInt - SYSINTR_DEVICE?
        bltz    a0, NKIRet                      // invalid idInt if (a0) < 0
        move    v0, zero                        // (delay slot) return 0
        
        sltu    v0, a0, SYSINTR_MAX_DEVICES     // v0 = (a0 < SYSINTR_MAX_DEVICES)
        beq     v0, zero, NKIRet                // out of range, return 0
        sll     a0, a0, 2                       // (delay slot) a0 *= 4

        // valid range, return IntrEvents[idInt-SYSINTR_DEVICES]
        lw      v0, IntrEvents(a0)

NKIRet:

        j       ra
        nop

        .set    at
        .set    reorder

        .end    NKIsSysIntrValid

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
LEAF_ENTRY(SetCPUHardwareWatch)
        .set noreorder
        
        lui     t0, 0x1fff
        ori     t0, t0, 0xfff8
        and     a0, a0, t0
        or      a0, a0, a1
        CP0_STOP_PREFETCH(mtc0, a0, $18, t0);
        nop
        nop
        mtc0    zero, $19
        nop
        nop
        j       ra
        nop
        
        .end SetCPUHardwareWatch


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
LEAF_ENTRY(SetCPUASID)
        .set noreorder

        //----- CeLogThreadMigrate -----
        //
        // NOTE : To make things relatively consistent, I'm going to make
        // the registers v0, t0-t9, a0, a1 available for use. On entry to
        // CeLogThreadMigrateMIPS, a0 will contain the handle of the new process.
        //
        // I'm assuming that at this point the only registers of these that
        // I need to preserve are A0 and RA.
        //

        lw      t0, CeLogStatus         // (t0) = KInfoTable[KINX_CELOGSTATUS]
        lui     t1, 0x2000              // (t1) = CELOGSTATUS_ENABLED_GENERAL
        and     t0, t0, t1              // (t0) = IsCeLogStatus(CELOGSTATUS_ENABLED_GENERAL)
        beq     zero, t0, celog10       // if false then skip CeLog call
        nop
        
        lw      t0, ThProc(a0)          // (t0) = ptr to new process
        lw      t1, PrcHandle(t0)       // (t1) = handle of new process
        lw      t0, hCurProc            // (t0) = current process handle
        beq     t0, t1, celog10         // if procs are equal then skip CeLog call
        nop

        subu    sp, 6*REG_SIZE          // adjust sp (2 for register save, + 4 for C calling convention
        S_REG   a0, 5*REG_SIZE(sp)      // save arg (pth)
        sw      ra, 4*REG_SIZE(sp)      // save RA

        move    a1, zero                // (a1) = 0

        jal     CeLogThreadMigrate
        move    a0, t1                  // (delay slot) (a0) = handle of new process


        lw      ra, 4*REG_SIZE(sp)      // restore RA
        L_REG   a0, 5*REG_SIZE(sp)      // restore arg
        addu    sp, 6*REG_SIZE          // adjust sp

celog10:
        //--- End CeLogThreadMigrate ---

        lw      t0, ThProc(a0)          // (t0) = ptr to current process
        lw      t1, ThAKey(a0)          // (t1) = thread's access key
        lw      t2, PrcHandle(t0)       // (t2) = handle of current process
        sw      t0, CurPrcPtr           // remember current process pointer
        sw      t1, CurAKey             // save access key for TLB handler
        lb      t1, PrcID(t0)           // (t0) = process ID
        beq     t1, zero, UseNKSection  // slot 1 -- use NKSection
        sw      t2, hCurProc            // remember current process handle (delay slot)

        // not slot 1, find it from section table
        lw      t2, PrcVMBase(t0)       // (t2) = memory section base address
        srl     t2, VA_SECTION-2        // (t2) = index into section table
        b       ContinueSetCpuASID
        lw      t2, SectionTable(t2)    // (t2) = process's memory section (delay slot)

UseNKSection:
        la      t2, NKSection

ContinueSetCpuASID:
        
#if ENTRYHI_PID != 0
        sll     t1, ENTRYHI_PID
#endif
        CP0_STOP_PREFETCH(mtc0, t1, entryhi, t0);    // set ASID
        j       ra
        sw      t2, SectionTable(zero)  // swap in default process slot
        
        .end SetCPUASID




        .struct 0
KCF_A0:         .space  REG_SIZE
KCF_A1:         .space  REG_SIZE
KCF_A2:         .space  REG_SIZE
KCF_A3:         .space  REG_SIZE
KCF_RA:         .space  REG_SIZE
KCF_SP:
KCF_LENGTH:

//------------------------------------------------------------------------------
//++
// The following code is never executed. Its purpose is to support unwinding
// through the call to the exception dispatcher.
//------------------------------------------------------------------------------
NESTED_ENTRY(xKCall, 0, zero)
        .set    noreorder
        .set    noat
        sw      sp,KCF_LENGTH(sp) // save stack pointer
        sw      ra,KCF_RA(sp)     // save return address
        PROLOGUE_END


//------------------------------------------------------------------------------
//

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -