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

📄 ppctrap.s

📁 wince下的源代码集合打包
💻 S
📖 第 1 页 / 共 5 页
字号:
//      TITLE("Interrupt and Exception Processing")
//++
//
// Copyright (c) 1996-2000 Microsoft Corporation.  All rights reserved.
//
// Module Name:
//
//    ppctrap.s
//
// Abstract:
//
//    This module implements the code necessary to field and process PowerPC
//    interrupt and exception conditions.
//
// WARNING: Some of the code in this module runs with relocation disabled and
// cannot directly reference kernel global data. However, the kernel data page is
// chosen to have the same virtual and physical address (0x5800) and can be used
// with relocation disabled.
//
// Environment:
//
//    Kernel mode only.
//
// Revision History:
//
//--

#include "ksppc.h"
#include "nkintr.h"
#include "psyscall.h"
#include "mem_ppc.h"
#include "kpage.h"



//
// Constants
//

#define HwInterruptVector       0x500   // Hardware interrupt vector
#define DecrementerVector       0x900   // Decrementer exception vector


//
//  Externs from mdppc.c
//
.extern CEProcessorType                 // DWORD CEProcessorType;
.extern ProcessorLevel                  // WORD  ProcessorLevel;
.extern ProcessorRevision               // WORD  ProcessorRevision;


#if 0   // SAVEGP
    .globl  _gp                     // Global pointer value set by linker
#endif
    .globl    KPageBlock
    .globl    NKSignon
    .globl    ObjectCall
    .globl    HandleException
    .globl    ServerCallReturn
    .globl    KernelRelocate
    .globl    OEMInitDebugSerial
    .globl    OEMInit
    .globl    OEMWriteDebugString
    .globl    KernelFindMemory
    .globl    KernelInit
    .globl    ExceptionDispatch
#if CELOG
    .globl    CeLogInterrupt
#endif


#define MSR_CLR_EE(reg)\
    rlwinm    reg, reg, 0, ~MSR_EE

#define MSR_CLR_ME(reg)\
    rlwinm    reg, reg, 0, ~MSR_ME

#define MSR_CLR_RI(reg)\
    rlwinm    reg, reg, 0, ~MSR_RI

#define MSR_CLR_POW(reg) \
    rlwinm    reg, reg, 0, ~MSR_POW

//
//  TLB management routines.
//
//  Include the processor-specific TLB management routines here:
//

#if PPC403
#include "ppc403.s"
#endif

#if PPC821
#include "ppc821.s"
#endif

//
// Shared low memory interrupt code
//
// This code is put into the kernel data page so that it can execute
// with relocation enabled or disabled. It performs its initial work without
// relocation and then enables relocation and jumps to the kernel handler in
// the kernel "un-mapped" space.
//

    .text

KPageHandlers:

// Low memory API call and return handler.
//
// Prepare a thread for an API call. Since this is a C level function
// call, it is not necessary to save the volatile CPU state.
//
// This code is located in the kernel page at 0x5000 so that it can
// run with relocation enabled or disabled and in kernel mode or user mode.
// The sequence is:
//    Entry in kernel mode with relocation disabled
//    Enable relocation
//    decode the API
//    Switch to user mode
//    invoke the API or return to API caller
//
// Entry  (r3-r10) = API arguments
//        (r11) = API call address (SRR0) - FIRST_METHOD
//        (r12) = previous Status (SRR1)
// Exit to API dispatch code in kernel with:
//        (r1) = kernel stack pointer
//        (r11) = API set & index
//        (r12) = caller's stack pointer
// Uses   r0, r11, r12, CR0, CR5

//
//  Fake Prologue required for unwinding. Save GP and RA on stack
//

   .set KPageAPIHandler, ($ - KPageHandlers) + LowHandlers
    mfmsr   r0                      // Get current MSR settings
    ori     r0, r0, (MSR_IR | MSR_DR | MSR_EE | MSR_RI | MSR_ME)
                                    // OR in new bits (in low half word)
    mtmsr   r0                      // enable relocation & interrupts
    rlwinm  r12, r12, MSR_BIT_PR+1, 1
                                    // (r12) = previous processor mode
    cmpwi   r11, -APICALL_SCALE
    stw     r3, CrParameter0(r1)    // store args onto the stack
    stw     r4, CrParameter1(r1)    // ...
    beq     APIReturn               // go pop the callstack for an API return
    stw     r5, CrParameter2(r1)    // ...
    stw     r6, CrParameter3(r1)    // ...
    stw     r7, CrParameter4(r1)    // ...
    stw     r8, CrParameter5(r1)    // ...
    stw     r9, CrParameter6(r1)    // ...
    stw     r10, CrParameter7(r1)   // ...
    mflr    r4                      // (r4) = Arg1, return address
    addi    r5, r1, CrParameter0    // (r5) = Arg2, ptr to API parameters
    srawi   r6, r11, 2              // (r6) = Arg3, API set & index
    stwu    r1, -StackFrameHeaderLength-8(r1)
    lis     r3, [hia]ObjectCall
    addi    r3, r3, [lo]ObjectCall  // (r0) == ptr to ObjectCall
    mtctr   r3
    addi    r3, r1, StackFrameHeaderLength
                                    // (r3) = Arg0, ptr to OCALLINFO struct
    stw     r12, 0(r3)              // store previous thread execution mode
    stw     r2, 4(r3)               // store caller's Global pointer
    lwz     r2, NKGp(0)
    bctrl                           // call ObjectCall(poci, ra, args, iMethod)

// Reload argument registers and invoke an API function.
//
// (r3) = pointer to an API function to invoke (0 if API completed)

    lwz     r12, StackFrameHeaderLength(r1)
                                    // (r12) = thread mode
    lwz     r1, 0(r1)               // clear working frame from the stack
    cmpwi   r12, 0
    mtctr   r3
    lwz     r3, CrParameter0(r1)    // reload argument registers from the stack
    lwz     r4, CrParameter1(r1)    // ...
    lwz     r5, CrParameter2(r1)    // ...
    lwz     r6, CrParameter3(r1)    // ...
    lwz     r7, CrParameter4(r1)    // ...
    lwz     r8, CrParameter5(r1)    // ...
    lwz     r9, CrParameter6(r1)    // ...
    lwz     r10, CrParameter7(r1)   // ...
    beq     APICall                 // invoke the function in kernel mode
    li      r0, SYSCALL_RETURN
    mtlr    r0                      // setup for api return interrupt
    mfmsr   r0                      // Get current MSR
    ori     r0, r0, (MSR_PR | MSR_EE | MSR_ME)
                                    // Set problem state bit to user mode
    mtmsr   r0                      // switch to user mode

    bctr                            //  and jump to the API function

// Invoke an API function in kernel mode. This may be due to the api being a
// kernel function or the thread running in kernel mode.
//
//    (ctr) = function address
//    (r2) = function's Global pointer
//    (r3-r10) = API arguments

APICall:
    bctrl                           // call API function
   .set APICallReturn, ($ - KPageHandlers) + LowHandlers
    li      r12, 0                  // (r12) = KERNEL_MODE
    stw     r3, CrParameter0(r1)    // save return value onto the stack
    stw     r4, CrParameter1(r1)    // ...
APIReturn:
    stwu    r1, -StackFrameHeaderLength-16(r1)
    lis     r3, [hia]ServerCallReturn
    addi    r3, r3, [lo]ServerCallReturn
                                    // (r3) = Ptr to ServerCallReturn
    mtctr   r3
    addi    r3, r1, StackFrameHeaderLength
                                    // (r3) = Arg0, ptr to OCALLINFO struct
    stw     r12, 0(r3)              // store previous thread execution mode
    lwz     r2, NKGp(0)
    bctrl                           // call ServerCallReturn(poci)

    lwz     r12, StackFrameHeaderLength(r1)
                                    // (r12) = thread mode
    lwz     r2, StackFrameHeaderLength+4(r1)
                                    // (r2) = original caller's Global ptr
    lwz     r1, 0(r1)               // clear working frame from the stack
    mtlr    r3
    cmpwi   r12, 0
    lwz     r3, CrParameter0(r1)    // restore return value registers from
                                    //   the stack
    lwz     r4, CrParameter1(r1)    // ...
    beqlr                           // return to kernel mode caller
    mfmsr   r0                      // Get current MSR
    ori     r0, r0, (MSR_PR | MSR_EE | MSR_ME)
                                    // Set problem state bit to user mode,
                                    //   enable interrupts and machine check
    mtmsr   r0                      // Switch to user mode
    blr                             //  and return


//
// Low memory common interrupt handling code
//
// This code is put into the kernel data page at so that it can execute
// with relocation enabled or disabled. It performs its initial work without
// relocation and then enables relocation and jumps to the kernel handler in
// the kernel "un-mapped" space.
//

//
// KPageHwInterruptHandler - Handler used for decrementer and hw interrupt
//  exceptions.  The code assumes the following entry and is running w/o
//  relocations or interrupts.
//
//  (r5) = Address of OEMInterruptHandler or OEMDecrementer
//  (SPRG1) = Original r14
//  (SPRG2) = Original r5
//

.set KPageHwInterruptHandler, ($ - KPageHandlers) + LowHandlers

    lha     r14, ReschedFlag(0)
    mtspr   SPRG3, r0
    mfcr    r0                      // (r0) = saved condition register
    subi    r14, r14, 256
    mtcrf   0x80, r14                // copy r6 sign bit to bit 0 of CR
    sth     r14, ReschedFlag(0)
    lwz     r14, CurThdPtr(0)        // (r6) = ptr to Current Thread struct
    bt-     0, hwh10                 // nested interrupt
    rlwinm  r14, r14, 0, 0x7fffffff   // (r6) = real address of THREAD
    stw     r1, TcxR1(r14)
    li      r1, KStack              // switch to kernel's stack
    b   hwh15

    //
    // A nested exception has occured. Create a temporary thread structure
    // on the stack and save the current state into that.
    //

hwh10:
    subi    r14, r1, TcxSizeof + STK_SLACK_SPACE
    stw     r1, TcxR1(r14)
    subi    r1, r14, StackFrameHeaderLength

hwh15:
    stw     r0, TcxCr(r14)
    stw     r3, TcxR3(r14)
    stw     r4, TcxR4(r14)
    mfspr   r0, SRR0                    // (r0) = faulting instr. address
    mfspr   r3, SRR1                    // (r3) = MSR at fault
    stw     r0, TcxIar(r14)
    stw     r3, TcxMsr(r14)


    //
    // Save the remaining context to allow for C calling convention:
    //
    //  (r14) = non-volatile thread context
    //  (r5) = Address of OEMInterruptHandler or OEMDecrementer
    //  (r6) = real address ptr to THREAD
    //  (SPRG1) = original R14 value
    //  (SPRG2) = original R5 value
    //  (SPRG3) = original R0 value
    //
    //  R1, R3, CR, SRR0, & SRR1 saved into THREAD.ctx
    //

    stw     r7, TcxR7(r14)
    mfspr   r0, SPRG1                   // (r0) = original R4 value
    mfspr   r7, SPRG2                   // (r7) = original R5 value
    stw     r0, TcxR14(r14)
    stw     r7, TcxR5(r14)
    mfspr   r0, SPRG3                   // (r0) = original R0 value
    stw     r0, TcxR0(r14)
    mfxer   r7
    stw     r7, TcxXer(r14)
    mfctr   r0
    mflr    r7
    stw     r0, TcxCtr(r14)
    stw     r7, TcxLr(r14)
    stw     r2, TcxR2(r14)              // save Thread's Global pointer
    lwz     r2, NKGp(0)                 // (r2) = kernel's GP
    stw     r6, TcxR6(r14)
    stw     r8, TcxR8(r14)              // save volatile register state
    stw     r9, TcxR9(r14)              // ...
    stw     r10, TcxR10(r14)            // ...
    stw     r11, TcxR11(r14)            // ...
    stw     r12, TcxR12(r14)            // ...
    stw     r13, TcxR13(r14)            // ...


    //
    // Call the OEM supplied ISR.  The ISR requires that relocations be on so
    // we use the rfi instruction to simultaneously enable relocations and jump
    // to the ISR continue point (ISRContinue).  ISRContinue will call the OEM
    // supplied ISR code.
    //
    //  (r5) = KSEG address of the ISR (OEMDecrementer or OEMInterruptHandler)
    //  (r14) = non-volatile thread context
    // R0-R11, Cr, Lr, Ctr, SRR0, & SRR1 saved into THREAD.ctx
    //

    //
    // Setup the MSR that will be used while running ISR.  We
    // need:
    //
    //  - Relocations
    //  - Interrupts OFF
    //
    // NOTE: We do not explicitly turn interrupts off because this code enters
    //  with interrupts off.
    //
    //  (r14) = Non-volatile thread ctx
    //

    mfmsr   r0                          // Get current MSR
    MSR_CLR_ME(r0)                      // Machine check off
    ori r0, r0, (MSR_IR | MSR_DR | MSR_RI)
                                        // Relocations ON

    //
    // Setup SRR0 and SRR1 which are used for the rfi instruction
    //

    lis     r3, [hia]IsrContinue          // Load address of KSEG ISR continue point
    addi    r3, r3, [lo]IsrContinue       // ...

    mtspr   SRR1, r0			// MSR at fault
    mtspr   SRR0, r3			// address of IsrContinue code

    oris    r14, r14, 0x8000            // (r3) = virtual address of THREAD
    rfi                                 // jump to KSEG ISR continue point with relocations

//
// KPageGeneralHandler - General Handler for non-TLB and non-HW related interrupts.
//  Exceptions handled include: alignment, machine check, page fault, access
//  violation, etc.
//
// (r4) = interrupt type
// (r5) = interrupt data (DAR or SRR0)
// (SPRG1) = original R4 value

⌨️ 快捷键说明

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