test: psctxi64.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# psctxi64.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1998  Intel Corporation
    00004 Copyright (c) 1990  Microsoft Corporation
    00005
    00006 Module Name:
    00007
    00008     psctxi64.c
    00009
    00010 Abstract:
    00011
    00012     This module implements function to get and set the context of a thread.
    00013
    00014 Author:
    00015
    00016     David N. Cutler (davec) 1-Oct-1990
    00017
    00018 Revision History:
    00019
    00020 --*/
    00021 #include "psp.h"
    00022 #include <ia64.h>
    00023
    00024
    00025 #define ALIGN_NATS(Result, Source, Start, AddressOffset, Mask)    \
    00026     if (AddressOffset == Start) {                                       \
    00027         Result = (ULONGLONG)Source;                                     \
    00028     } else if (AddressOffset < Start) {                                 \
    00029         Result = (ULONGLONG)(Source << (Start - AddressOffset));        \
    00030     } else {                                                            \
    00031         Result = (ULONGLONG)((Source >> (AddressOffset - Start)) |      \
    00032                              (Source << (64 + Start - AddressOffset))); \
    00033     }                                                                   \
    00034     Result = Result & (ULONGLONG)Mask
    00035
    00036 #define EXTRACT_NATS(Result, Source, Start, AddressOffset, Mask)        \
    00037     Result = (ULONGLONG)(Source & (ULONGLONG)Mask);                     \
    00038     if (AddressOffset < Start) {                                        \
    00039         Result = Result >> (Start - AddressOffset);                     \
    00040     } else if (AddressOffset > Start) {                                 \
    00041         Result = ((Result << (AddressOffset - Start)) |                 \
    00042                   (Result >> (64 + Start - AddressOffset)));            \
    00043     }
    00044
    00045
    00046 VOID
    00047 KiGetDebugContext (
    00048     IN PKTRAP_FRAME TrapFrame,
    00049     IN OUT PCONTEXT ContextFrame
    00050     );
    00051
    00052 VOID
    00053 KiSetDebugContext (
    00054     IN OUT PKTRAP_FRAME TrapFrame,
    00055     IN PCONTEXT ContextFrame,
    00056     IN KPROCESSOR_MODE ProcessorMode
    00057     );
    00058
    00059 VOID
    00060 KiFlushUserRseState (
    00061     IN PKTRAP_FRAME TrapFrame
    00062     );
    00063
    00064 VOID
    00065 PspGetContext (
    00066     IN PKTRAP_FRAME                   TrapFrame,
    00067     IN PKNONVOLATILE_CONTEXT_POINTERS ContextPointers,
    00068     IN OUT PCONTEXT                   ContextEM
    00069     )
    00070
    00071 /*++
    00072
    00073 Routine Description:
    00074
    00075     This function selectively moves the contents of the specified trap frame
    00076     and nonvolatile context to the specified context record.
    00077
    00078 Arguments:
    00079
    00080     TrapFrame -         Supplies a pointer to a trap frame.
    00081
    00082     ContextPointers -   Supplies the address of context pointers record.
    00083
    00084     ContextEM -         Supplies the address of a context record.
    00085
    00086 Return Value:
    00087
    00088     None.
    00089
    00090     N.B. The side effect of this routine is that the dirty user stacked
    00091          registers that were flushed into the kernel backing store are
    00092          copied backed into the user backing store and the trap frame
    00093          will be modified as a result of that.
    00094
    00095 --*/
    00096
    00097 {
    00098
    00099     ULONGLONG IntNats1, IntNats2 = 0;
    00100     USHORT R1Offset, R4Offset;
    00101     SHORT Temp, BsFrameSize;
    00102
    00103     if ((ContextEM->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) {
    00104
    00105         ContextEM->IntGp = TrapFrame->IntGp;
    00106         ContextEM->IntSp = TrapFrame->IntSp;
    00107         ContextEM->ApUNAT = TrapFrame->ApUNAT;
    00108         ContextEM->BrRp = TrapFrame->BrRp;
    00109         ContextEM->ApCCV = TrapFrame->ApCCV;
    00110         ContextEM->ApDCR = TrapFrame->ApDCR;
    00111
    00112         ContextEM->StFPSR = TrapFrame->StFPSR;
    00113         ContextEM->StIPSR = TrapFrame->StIPSR;
    00114         ContextEM->StIIP = TrapFrame->StIIP;
    00115         ContextEM->StIFS = TrapFrame->StIFS;
    00116
    00117         //
    00118         // Get RSE control states from the trap frame.
    00119         //
    00120
    00121         ContextEM->RsPFS = TrapFrame->RsPFS;
    00122         ContextEM->RsRSC = TrapFrame->RsRSC;
    00123         ContextEM->RsRNAT = TrapFrame->RsRNAT;
    00124
    00125         if (TRAP_FRAME_TYPE(TrapFrame) == SYSCALL_FRAME) {
    00126             BsFrameSize = (SHORT) (TrapFrame->StIFS >> PFS_SIZE_SHIFT) & PFS_SIZE_MASK;
    00127         } else {
    00128             BsFrameSize = (SHORT) TrapFrame->StIFS & PFS_SIZE_MASK;
    00129         }
    00130         Temp = BsFrameSize - (SHORT)((TrapFrame->RsBSP >> 3) & NAT_BITS_PER_RNAT_REG);
    00131         while (Temp > 0) {
    00132             BsFrameSize++;
    00133             Temp -= NAT_BITS_PER_RNAT_REG;
    00134         }
    00135
    00136         ContextEM->RsBSP = TrapFrame->RsBSP - (BsFrameSize * 8);
    00137         ContextEM->RsBSPSTORE = ContextEM->RsBSP;
    00138
    00139         //
    00140         // Get preserved applicaton registers
    00141         //
    00142
    00143         ContextEM->ApLC = *ContextPointers->ApLC;
    00144         ContextEM->ApEC = (*ContextPointers->ApEC >> PFS_EC_SHIFT) & PFS_EC_MASK;
    00145
    00146         //
    00147         // Get iA status
    00148         //
    00149
    00150         ContextEM->StFSR = *ContextPointers->StFSR;
    00151         ContextEM->StFIR = *ContextPointers->StFIR;
    00152         ContextEM->StFDR = *ContextPointers->StFDR;
    00153         ContextEM->Cflag = *ContextPointers->Cflag;
    00154
    00155     }
    00156
    00157     if ((ContextEM->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) {
    00158
    00159         ContextEM->IntT0 = TrapFrame->IntT0;
    00160         ContextEM->IntT1 = TrapFrame->IntT1;
    00161         ContextEM->IntT2 = TrapFrame->IntT2;
    00162         ContextEM->IntT3 = TrapFrame->IntT3;
    00163         ContextEM->IntT4 = TrapFrame->IntT4;
    00164         ContextEM->IntV0 = TrapFrame->IntV0;
    00165         ContextEM->IntTeb = TrapFrame->IntTeb;
    00166         ContextEM->Preds = TrapFrame->Preds;
    00167
    00168         //
    00169         // t5 - t22
    00170         //
    00171
    00172         memcpy(&ContextEM->IntT5, &TrapFrame->IntT5, 18*sizeof(ULONGLONG));
    00173
    00174
    00175         //
    00176         // Get branch registers
    00177         //
    00178
    00179         ContextEM->BrT0 = TrapFrame->BrT0;
    00180         ContextEM->BrT1 = TrapFrame->BrT1;
    00181
    00182         ContextEM->BrS0 = *ContextPointers->BrS0;
    00183         ContextEM->BrS1 = *ContextPointers->BrS1;
    00184         ContextEM->BrS2 = *ContextPointers->BrS2;
    00185         ContextEM->BrS3 = *ContextPointers->BrS3;
    00186         ContextEM->BrS4 = *ContextPointers->BrS4;
    00187
    00188         //
    00189         // Get integer registers s0 - s3 from exception frame.
    00190         //
    00191
    00192         ContextEM->IntS0 = *ContextPointers->IntS0;
    00193         ContextEM->IntS1 = *ContextPointers->IntS1;
    00194         ContextEM->IntS2 = *ContextPointers->IntS2;
    00195         ContextEM->IntS3 = *ContextPointers->IntS3;
    00196         IntNats2 |= (((*ContextPointers->IntS0Nat >> (((ULONG_PTR)ContextPointers->IntS0 & 0x1F8) >> 3)) & 0x1) << 4);
    00197         IntNats2 |= (((*ContextPointers->IntS1Nat >> (((ULONG_PTR)ContextPointers->IntS1 & 0x1F8) >> 3)) & 0x1) << 5);
    00198         IntNats2 |= (((*ContextPointers->IntS2Nat >> (((ULONG_PTR)ContextPointers->IntS2 & 0x1F8) >> 3)) & 0x1) << 6);
    00199         IntNats2 |= (((*ContextPointers->IntS3Nat >> (((ULONG_PTR)ContextPointers->IntS3 & 0x1F8) >> 3)) & 0x1) << 7);
    00200
    00201         //
    00202         // Get the integer nats field in the context
    00203         // *ContextPointers->IntNats has Nats for preserved regs
    00204         //
    00205
    00206         R1Offset = (USHORT)((ULONG_PTR)(&TrapFrame->IntGp) >> 3) & 0x3f;
    00207         R4Offset = (USHORT)((ULONG_PTR)(ContextPointers->IntS0) >> 3) & 0x3f;
    00208         ALIGN_NATS(IntNats1, TrapFrame->IntNats, 1, R1Offset, 0xFFFFFF0E);
    00209
    00210         ContextEM->IntNats = IntNats1 | IntNats2;
    00211
    00212 #ifdef DEBUG
    00213         DbgPrint("PspGetContext INTEGER: R1Offset = 0x%x, TF->IntNats = 0x%I64x, IntNats1 = 0x%I64x\n",
    00214                R1Offset, TrapFrame->IntNats, IntNats1);
    00215 #endif
    00216
    00217     }
    00218
    00219     if ((ContextEM->ContextFlags & CONTEXT_LOWER_FLOATING_POINT) == CONTEXT_LOWER_FLOATING_POINT) {
    00220
    00221         //
    00222         // Get EM + ia32 FP status
    00223         //
    00224
    00225         ContextEM->StFPSR = TrapFrame->StFPSR;
    00226         ContextEM->StFSR  = *ContextPointers->StFSR;
    00227         ContextEM->StFIR  = *ContextPointers->StFIR;
    00228         ContextEM->StFDR  = *ContextPointers->StFDR;
    00229
    00230         //
    00231         // Get floating registers fs0 - fs19
    00232         //
    00233
    00234         ContextEM->FltS0 = *ContextPointers->FltS0;
    00235         ContextEM->FltS1 = *ContextPointers->FltS1;
    00236         ContextEM->FltS2 = *ContextPointers->FltS2;
    00237         ContextEM->FltS3 = *ContextPointers->FltS3;
    00238
    00239         ContextEM->FltS4 = *ContextPointers->FltS4;
    00240         ContextEM->FltS5 = *ContextPointers->FltS5;
    00241         ContextEM->FltS6 = *ContextPointers->FltS6;
    00242         ContextEM->FltS7 = *ContextPointers->FltS7;
    00243
    00244         ContextEM->FltS8 = *ContextPointers->FltS8;
    00245         ContextEM->FltS9 = *ContextPointers->FltS9;
    00246         ContextEM->FltS10 = *ContextPointers->FltS10;
    00247         ContextEM->FltS11 = *ContextPointers->FltS11;
    00248
    00249         ContextEM->FltS12 = *ContextPointers->FltS12;
    00250         ContextEM->FltS13 = *ContextPointers->FltS13;
    00251         ContextEM->FltS14 = *ContextPointers->FltS14;
    00252         ContextEM->FltS15 = *ContextPointers->FltS15;
    00253
    00254         ContextEM->FltS16 = *ContextPointers->FltS16;
    00255         ContextEM->FltS17 = *ContextPointers->FltS17;
    00256         ContextEM->FltS18 = *ContextPointers->FltS18;
    00257         ContextEM->FltS19 = *ContextPointers->FltS19;
    00258
    00259         //
    00260         // Get floating registers ft0 - ft9 from trap frame.
    00261         //
    00262
    00263         RtlCopyIa64FloatRegisterContext(&ContextEM->FltT0,
    00264                                         &TrapFrame->FltT0,
    00265                                         sizeof(FLOAT128) * (10));
    00266     }
    00267
    00268     if ((ContextEM->ContextFlags & CONTEXT_HIGHER_FLOATING_POINT) == CONTEXT_HIGHER_FLOATING_POINT) {
    00269
    00270         //
    00271         // Get EM + ia32 FP status
    00272         //
    00273
    00274         ContextEM->StFPSR = TrapFrame->StFPSR;
    00275         ContextEM->StFSR  = *ContextPointers->StFSR;
    00276         ContextEM->StFIR  = *ContextPointers->StFIR;
    00277         ContextEM->StFDR  = *ContextPointers->StFDR;
    00278
    00279         //
    00280         // Get floating regs f32 - f127 from higher floating point save area
    00281         //
    00282
    00283         if (TrapFrame->PreviousMode == UserMode) {
    00284             RtlCopyIa64FloatRegisterContext(
    00285                 &ContextEM->FltF32,
    00286                 (PFLOAT128)GET_HIGH_FLOATING_POINT_REGISTER_SAVEAREA(),
    00287                 96*sizeof(FLOAT128)
    00288                 );
    00289         }
    00290     }
    00291
    00292     //
    00293     // Get h/w debug register context
    00294     //
    00295
    00296     if ((ContextEM->ContextFlags & CONTEXT_DEBUG) == CONTEXT_DEBUG) {
    00297         KiGetDebugContext(TrapFrame, ContextEM);
    00298     }
    00299
    00300     return;
    00301 }
    00302
    00303 VOID
    00304 PspSetContext (
    00305     IN OUT PKTRAP_FRAME               TrapFrame,
    00306     IN PKNONVOLATILE_CONTEXT_POINTERS ContextPointers,
    00307     IN PCONTEXT                       ContextEM,
    00308     IN KPROCESSOR_MODE                ProcessorMode
    00309     )
    00310
    00311 /*++
    00312
    00313 Routine Description:
    00314
    00315     This function selectively moves the contents of the specified context
    00316     record to the specified trap frame and nonvolatile context.
    00317
    00318     We're expecting a plabel to have been passed in the IIP (we won't have a valid
    00319     Global pointer) and if we have a plabel we fill in the correct Global pointer and
    00320     IIP. Technically, the GP is part of the CONTEXT_CONTROL with the EM architecture
    00321     so we only need to check to see if CONTEXT_CONTROL has been specified.
    00322
    00323 Arguments:
    00324
    00325     TrapFrame -           Supplies the address of the trap frame.
    00326
    00327     ContextPointers -   Supplies the address of context pointers record.
    00328
    00329     ContextEM -         Supplies the address of a context record.
    00330
    00331     ProcessorMode -     Supplies the processor mode to use when sanitizing
    00332                         the PSR and FSR.
    00333
    00334 Return Value:
    00335
    00336     None.
    00337
    00338 --*/
    00339
    00340 {
    00341     SHORT BsFrameSize;
    00342     SHORT TempFrameSize;
    00343     USHORT R1Offset, R4Offset;
    00344     USHORT RNatSaveIndex;
    00345
    00346     if ((ContextEM->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) {
    00347
    00348         if (ContextEM->IntGp == 0) {
    00349             try {
    00350
    00351                 //
    00352                 // Make sure we have read access to the plabel
    00353                 //
    00354
    00355                 ProbeForRead(ContextEM->StIIP,
    00356                              sizeof(PLABEL_DESCRIPTOR),
    00357                              sizeof(ULONGLONG));
    00358                 ContextEM->IntGp = ((PPLABEL_DESCRIPTOR)(ContextEM->StIIP))->GlobalPointer;
    00359                 ContextEM->StIIP = ((PPLABEL_DESCRIPTOR)(ContextEM->StIIP))->EntryPoint;
    00360
    00361             } except(EXCEPTION_EXECUTE_HANDLER) {
    00362
    00363                 //
    00364                 // Remote thread does not have access to the plabel. Just
    00365                 // let the thread take the exception.
    00366                 //
    00367
    00368                 ;
    00369             }
    00370         }
    00371
    00372         TrapFrame->IntGp = ContextEM->IntGp;
    00373         TrapFrame->IntSp = ContextEM->IntSp;
    00374         TrapFrame->ApUNAT = ContextEM->ApUNAT;
    00375         TrapFrame->BrRp = ContextEM->BrRp;
    00376         TrapFrame->ApCCV = ContextEM->ApCCV;
    00377         TrapFrame->ApDCR = SANITIZE_DCR(ContextEM->ApDCR, ProcessorMode);
    00378
    00379         //
    00380         // Set preserved applicaton registers.
    00381         //
    00382
    00383         *ContextPointers->ApLC = ContextEM->ApLC;
    00384         *ContextPointers->ApEC &= ~(PFS_EC_MASK << PFS_EC_SHIFT);
    00385         *ContextPointers->ApEC |= ((ContextEM->ApEC & PFS_EC_MASK) << PFS_EC_SHIFT);
    00386
    00387         TrapFrame->StFPSR = SANITIZE_FSR(ContextEM->StFPSR, ProcessorMode);
    00388         TrapFrame->StIIP = ContextEM->StIIP;
    00389         TrapFrame->StIFS = SANITIZE_IFS(ContextEM->StIFS, ProcessorMode);
    00390         TrapFrame->StIPSR = SANITIZE_PSR(ContextEM->StIPSR, ProcessorMode);
    00391
    00392         if (((TrapFrame->StIPSR >> PSR_RI) & 3) == 3) {
    00393
    00394             //
    00395             // 3 is an invalid slot number; sanitize it to zero
    00396             //
    00397
    00398             TrapFrame->StIPSR &= ~(3i64 << PSR_RI);
    00399         }
    00400
    00401         TrapFrame->RsPFS = ContextEM->RsPFS;
    00402
    00403         if (TRAP_FRAME_TYPE(TrapFrame) == SYSCALL_FRAME) {
    00404             if (TrapFrame->StIPSR & (1i64 << PSR_SS)) {
    00405
    00406                 //
    00407                 // if the psr.ss bit is set when the target thread is in a
    00408                 // system call, the psr.lp bit has to be set in order for
    00409                 // the target thread to pick up its setting when it returns
    00410                 // from the system call.  i.e. psr.ss is not saved and
    00411                 // and restored by the EPC system call handler.
    00412                 //
    00413
    00414                 TrapFrame->StIPSR |= (1i64 << PSR_LP);
    00415             }
    00416
    00417             //
    00418             // in the case of EPC system call, the frame size that needs to be
    00419             // adjusted is the local frame size, not the total framze size.
    00420             //
    00421
    00422             BsFrameSize = (SHORT) (ContextEM->StIFS >> PFS_SIZE_SHIFT) & PFS_SIZE_MASK;
    00423         } else {
    00424             BsFrameSize = (SHORT) ContextEM->StIFS & PFS_SIZE_MASK;
    00425         }
    00426         RNatSaveIndex = (USHORT)((ContextEM->RsBSP >> 3) & NAT_BITS_PER_RNAT_REG);
    00427
    00428         TempFrameSize = RNatSaveIndex + BsFrameSize - NAT_BITS_PER_RNAT_REG;
    00429         while (TempFrameSize >= 0) {
    00430             BsFrameSize++;
    00431             TempFrameSize -= NAT_BITS_PER_RNAT_REG;
    00432         }
    00433
    00434         TrapFrame->RsBSPSTORE = ContextEM->RsBSPSTORE + BsFrameSize * 8;
    00435         TrapFrame->RsBSP = TrapFrame->RsBSPSTORE;
    00436         TrapFrame->RsRSC = ContextEM->RsRSC;
    00437         TrapFrame->RsRNAT = ContextEM->RsRNAT;
    00438
    00439 #ifdef DEBUG
    00440         DbgPrint ("PspSetContext CONTROL: TrapFrame->RsRNAT = 0x%I64x\n",
    00441                 TrapFrame->RsRNAT);
    00442 #endif
    00443
    00444         //
    00445         // DebugActive controls h/w debug registers. Set if new psr.db = 1
    00446         //
    00447
    00448         KeGetCurrentThread()->DebugActive = ((TrapFrame->StIPSR & (1I64 << PSR_DB)) != 0);
    00449
    00450         //
    00451         // Set iA status
    00452         // *** TBD SANATIZE??
    00453         //
    00454
    00455         *ContextPointers->StFSR = ContextEM->StFSR;
    00456         *ContextPointers->StFIR = ContextEM->StFIR;
    00457         *ContextPointers->StFDR = ContextEM->StFDR;
    00458         *ContextPointers->Cflag = ContextEM->Cflag;
    00459
    00460     }
    00461
    00462     if ((ContextEM->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) {
    00463
    00464         TrapFrame->IntT0 = ContextEM->IntT0;
    00465         TrapFrame->IntT1 = ContextEM->IntT1;
    00466         TrapFrame->IntT2 = ContextEM->IntT2;
    00467         TrapFrame->IntT3 = ContextEM->IntT3;
    00468         TrapFrame->IntT4 = ContextEM->IntT4;
    00469         TrapFrame->IntV0 = ContextEM->IntV0;
    00470         TrapFrame->IntTeb = ContextEM->IntTeb;
    00471         TrapFrame->Preds = ContextEM->Preds;
    00472
    00473         //
    00474         //  t5 - t2
    00475         //
    00476
    00477         RtlCopyMemory(&TrapFrame->IntT5, &ContextEM->IntT5, 18*sizeof(ULONGLONG));
    00478
    00479         //
    00480         // Set the integer nats fields
    00481         //
    00482
    00483         R1Offset = (USHORT)((ULONG_PTR)(&TrapFrame->IntGp) >> 3) & 0x3f;
    00484
    00485         EXTRACT_NATS(TrapFrame->IntNats, ContextEM->IntNats,
    00486                      1, R1Offset, 0xFFFFFF0E);
    00487
    00488         //
    00489         // Set the preserved integer NAT fields
    00490         //
    00491
    00492         R4Offset = (USHORT)((ULONG_PTR)(ContextPointers->IntS0) >> 3) & 0x3f;
    00493
    00494         //
    00495         // BUGBUG: TBD
    00496         //
    00497         // EXTRACT_NATS(*ContextPointers->IntNats, ContextEM->IntNats,
    00498         //           4, R4Offset, 0xF0);
    00499
    00500         *ContextPointers->IntS0 = ContextEM->IntS0;
    00501         *ContextPointers->IntS1 = ContextEM->IntS1;
    00502         *ContextPointers->IntS2 = ContextEM->IntS2;
    00503         *ContextPointers->IntS3 = ContextEM->IntS3;
    00504
    00505         *ContextPointers->IntS0Nat &= ~(0x1 << (((ULONG_PTR)ContextPointers->IntS0 & 0x1F8) >> 3));
    00506         *ContextPointers->IntS1Nat &= ~(0x1 << (((ULONG_PTR)ContextPointers->IntS1 & 0x1F8) >> 3));
    00507         *ContextPointers->IntS2Nat &= ~(0x1 << (((ULONG_PTR)ContextPointers->IntS2 & 0x1F8) >> 3));
    00508         *ContextPointers->IntS3Nat &= ~(0x1 << (((ULONG_PTR)ContextPointers->IntS3 & 0x1F8) >> 3));
    00509
    00510         *ContextPointers->IntS0Nat |= (((ContextEM->IntNats >> 4) & 0x1) << (((ULONG_PTR)ContextPointers->IntS0 & 0x1F8) >> 3));
    00511         *ContextPointers->IntS1Nat |= (((ContextEM->IntNats >> 4) & 0x1) << (((ULONG_PTR)ContextPointers->IntS1 & 0x1F8) >> 3));
    00512         *ContextPointers->IntS2Nat |= (((ContextEM->IntNats >> 4) & 0x1) << (((ULONG_PTR)ContextPointers->IntS2 & 0x1F8) >> 3));
    00513         *ContextPointers->IntS3Nat |= (((ContextEM->IntNats >> 4) & 0x1) << (((ULONG_PTR)ContextPointers->IntS3 & 0x1F8) >> 3));
    00514
    00515 #ifdef DEBUG
    00516         DbgPrint("PspSetContext INTEGER: R1Offset = 0x%x, TF->IntNats = 0x%I64x, Context->IntNats = 0x%I64x\n",
    00517                R1Offset, TrapFrame->IntNats, ContextEM->IntNats);
    00518 #endif
    00519
    00520         *ContextPointers->BrS0 = ContextEM->BrS0;
    00521         *ContextPointers->BrS1 = ContextEM->BrS1;
    00522         *ContextPointers->BrS2 = ContextEM->BrS2;
    00523         *ContextPointers->BrS3 = ContextEM->BrS3;
    00524         *ContextPointers->BrS4 = ContextEM->BrS4;
    00525         TrapFrame->BrT0 = ContextEM->BrT0;
    00526         TrapFrame->BrT1 = ContextEM->BrT1;
    00527     }
    00528
    00529     if ((ContextEM->ContextFlags & CONTEXT_LOWER_FLOATING_POINT) == CONTEXT_LOWER_FLOATING_POINT) {
    00530
    00531         TrapFrame->StFPSR = SANITIZE_FSR(ContextEM->StFPSR, ProcessorMode);
    00532         *ContextPointers->StFSR = ContextEM->StFSR;
    00533         *ContextPointers->StFIR = ContextEM->StFIR;
    00534         *ContextPointers->StFDR = ContextEM->StFDR;
    00535
    00536         //
    00537         // Set floating registers fs0 - fs19.
    00538         //
    00539
    00540         *ContextPointers->FltS0 = ContextEM->FltS0;
    00541         *ContextPointers->FltS1 = ContextEM->FltS1;
    00542         *ContextPointers->FltS2 = ContextEM->FltS2;
    00543         *ContextPointers->FltS3 = ContextEM->FltS3;
    00544
    00545         *ContextPointers->FltS4 = ContextEM->FltS4;
    00546         *ContextPointers->FltS5 = ContextEM->FltS5;
    00547         *ContextPointers->FltS6 = ContextEM->FltS6;
    00548         *ContextPointers->FltS7 = ContextEM->FltS7;
    00549
    00550         *ContextPointers->FltS8 = ContextEM->FltS8;
    00551         *ContextPointers->FltS9 = ContextEM->FltS9;
    00552         *ContextPointers->FltS10 = ContextEM->FltS10;
    00553         *ContextPointers->FltS11 = ContextEM->FltS11;
    00554
    00555         *ContextPointers->FltS12 = ContextEM->FltS12;
    00556         *ContextPointers->FltS13 = ContextEM->FltS13;
    00557         *ContextPointers->FltS14 = ContextEM->FltS14;
    00558         *ContextPointers->FltS15 = ContextEM->FltS15;
    00559
    00560         *ContextPointers->FltS16 = ContextEM->FltS16;
    00561         *ContextPointers->FltS17 = ContextEM->FltS17;
    00562         *ContextPointers->FltS18 = ContextEM->FltS18;
    00563         *ContextPointers->FltS19 = ContextEM->FltS19;
    00564
    00565         //
    00566         // Set floating registers ft0 - ft9.
    00567         //
    00568
    00569         RtlCopyIa64FloatRegisterContext(&TrapFrame->FltT0,
    00570                                         &ContextEM->FltT0,
    00571                                         sizeof(FLOAT128) * (10));
    00572     }
    00573
    00574     if ((ContextEM->ContextFlags & CONTEXT_HIGHER_FLOATING_POINT) == CONTEXT_HIGHER_FLOATING_POINT) {
    00575
    00576
    00577         TrapFrame->StFPSR = SANITIZE_FSR(ContextEM->StFPSR, ProcessorMode);
    00578         *ContextPointers->StFSR = ContextEM->StFSR;
    00579         *ContextPointers->StFIR = ContextEM->StFIR;
    00580         *ContextPointers->StFDR = ContextEM->StFDR;
    00581
    00582         if (ProcessorMode == UserMode) {
    00583
    00584             //
    00585             // Update the higher floating point save area (f32-f127) and
    00586             // set the corresponding modified bit in the PSR to 1.
    00587             //
    00588
    00589             RtlCopyIa64FloatRegisterContext(
    00590                 (PFLOAT128)GET_HIGH_FLOATING_POINT_REGISTER_SAVEAREA(),
    00591                 &ContextEM->FltF32,
    00592                 96*sizeof(FLOAT128));
    00593
    00594             //
    00595             // set the dfh bit to force a reload of the high fp register
    00596             // set on the next user access
    00597             //
    00598
    00599             TrapFrame->StIPSR |= (1i64 << PSR_DFH);
    00600         }
    00601
    00602     }
    00603
    00604     //
    00605     // Set debug register contents if specified.
    00606     //
    00607
    00608     if ((ContextEM->ContextFlags & CONTEXT_DEBUG) == CONTEXT_DEBUG) {
    00609         KiSetDebugContext (TrapFrame, ContextEM, ProcessorMode);
    00610     }
    00611
    00612     return;
    00613 }
    00614
    00615 VOID
    00616 PspGetSetContextSpecialApcMain (
    00617     IN PKAPC Apc,
    00618     IN PKNORMAL_ROUTINE *NormalRoutine,
    00619     IN PVOID *NormalContext,
    00620     IN PVOID *SystemArgument1,
    00621     IN PVOID *SystemArgument2
    00622     )
    00623
    00624 /*++
    00625
    00626 Routine Description:
    00627
    00628     This function either captures the user mode state of the current
    00629     thread, or sets the user mode state of the current thread. The
    00630     operation type is determined by the value of SystemArgument1. A
    00631     zero value is used for get context, and a nonzero value is used
    00632     for set context.
    00633
    00634 Arguments:
    00635
    00636     Apc - Supplies a pointer to the APC control object that caused entry
    00637           into this routine.
    00638
    00639     NormalRoutine - Supplies a pointer to the normal routine function that
    00640         was specified when the APC was initialized. This parameter is not
    00641         used.
    00642
    00643     NormalContext - Supplies a pointer to an arbitrary data structure that
    00644         was specified when the APC was initialized. This parameter is not
    00645         used.
    00646
    00647     SystemArgument1, SystemArgument2 - Supplies a set of two pointers to two
    00648         arguments that contain untyped data.
    00649         The first arguement is used to distinguish between get and set requests.
    00650             A value of zero  signifies that GetThreadContext was requested.
    00651             A non-zero value signifies that SetThreadContext was requested.
    00652         The Second arguement has the thread handle. The second arguement is
    00653         not used.
    00654
    00655 Return Value:
    00656
    00657     None.
    00658
    00659 --*/
    00660
    00661 {
    00662     PGETSETCONTEXT                ContextInfo;
    00663     KNONVOLATILE_CONTEXT_POINTERS ContextPointers;  // Not currently used, needed later.
    00664     CONTEXT                       ContextRecord;
    00665     ULONGLONG                     ControlPc;
    00666     FRAME_POINTERS                EstablisherFrame;
    00667     PRUNTIME_FUNCTION             FunctionEntry;
    00668     BOOLEAN                       InFunction;
    00669     PETHREAD                      Thread;
    00670     PKTRAP_FRAME                  TrFrame1;
    00671     ULONGLONG                     ImageBase;
    00672     ULONGLONG                     TargetGp;
    00673
    00674     //
    00675     // Get the address of the context frame and compute the address of the
    00676     // system entry trap frame.
    00677     //
    00678
    00679     ContextInfo = CONTAINING_RECORD(Apc, GETSETCONTEXT, Apc);
    00680
    00681     TrFrame1 = (PKTRAP_FRAME)(((ULONG_PTR)PsGetCurrentThread()->Tcb.InitialStack
    00682                     - KTHREAD_STATE_SAVEAREA_LENGTH - KTRAP_FRAME_LENGTH));
    00683
    00684     //
    00685     // Capture the current thread context and set the initial control PC
    00686     // value.
    00687     //
    00688
    00689     RtlCaptureContext(&ContextRecord);
    00690     ControlPc = ContextRecord.BrRp;
    00691
    00692     //
    00693     // Initialize context pointers for the nonvolatile integer and floating
    00694     // registers.
    00695     //
    00696
    00697     ContextPointers.FltS0 = &ContextRecord.FltS0;
    00698     ContextPointers.FltS1 = &ContextRecord.FltS1;
    00699     ContextPointers.FltS2 = &ContextRecord.FltS2;
    00700     ContextPointers.FltS3 = &ContextRecord.FltS3;
    00701     ContextPointers.FltS4 = &ContextRecord.FltS4;
    00702     ContextPointers.FltS5 = &ContextRecord.FltS5;
    00703     ContextPointers.FltS6 = &ContextRecord.FltS6;
    00704     ContextPointers.FltS7 = &ContextRecord.FltS7;
    00705     ContextPointers.FltS8 = &ContextRecord.FltS8;
    00706     ContextPointers.FltS9 = &ContextRecord.FltS9;
    00707     ContextPointers.FltS10 = &ContextRecord.FltS10;
    00708     ContextPointers.FltS11 = &ContextRecord.FltS11;
    00709     ContextPointers.FltS12 = &ContextRecord.FltS12;
    00710     ContextPointers.FltS13 = &ContextRecord.FltS13;
    00711     ContextPointers.FltS14 = &ContextRecord.FltS14;
    00712     ContextPointers.FltS15 = &ContextRecord.FltS15;
    00713     ContextPointers.FltS16 = &ContextRecord.FltS16;
    00714     ContextPointers.FltS17 = &ContextRecord.FltS17;
    00715     ContextPointers.FltS18 = &ContextRecord.FltS18;
    00716     ContextPointers.FltS19 = &ContextRecord.FltS19;
    00717
    00718     ContextPointers.IntS0 = &ContextRecord.IntS0;
    00719     ContextPointers.IntS1 = &ContextRecord.IntS1;
    00720     ContextPointers.IntS2 = &ContextRecord.IntS2;
    00721     ContextPointers.IntS3 = &ContextRecord.IntS3;
    00722     ContextPointers.IntSp = &ContextRecord.IntSp;
    00723
    00724     ContextPointers.BrS0 = &ContextRecord.BrS0;
    00725     ContextPointers.BrS1 = &ContextRecord.BrS1;
    00726     ContextPointers.BrS2 = &ContextRecord.BrS2;
    00727     ContextPointers.BrS3 = &ContextRecord.BrS3;
    00728     ContextPointers.BrS4 = &ContextRecord.BrS4;
    00729
    00730     ContextPointers.ApLC = &ContextRecord.ApLC;
    00731     ContextPointers.ApEC = &ContextRecord.ApEC;
    00732
    00733     ContextPointers.StFSR = &ContextRecord.StFSR;
    00734     ContextPointers.StFIR = &ContextRecord.StFIR;
    00735     ContextPointers.StFDR = &ContextRecord.StFDR;
    00736     ContextPointers.Cflag = &ContextRecord.Cflag;
    00737
    00738     //
    00739     // Start with the frame specified by the context record and virtually
    00740     // unwind call frames until the system entry trap frame is encountered.
    00741     //
    00742
    00743     do {
    00744
    00745         //
    00746         // Lookup the function table entry using the point at which control
    00747         // left the procedure.
    00748         //
    00749
    00750         FunctionEntry = RtlLookupFunctionEntry(ControlPc, &ImageBase, &TargetGp);
    00751
    00752         //
    00753         // If there is a function table entry for the routine, then virtually
    00754         // unwind to the caller of the current routine to obtain the address
    00755         // where control left the caller.
    00756         //
    00757
    00758         if (FunctionEntry != NULL) {
    00759             ControlPc = RtlVirtualUnwind(ImageBase,
    00760                                          ControlPc,
    00761                                          FunctionEntry,
    00762                                          &ContextRecord,
    00763                                          &InFunction,
    00764                                          &EstablisherFrame,
    00765                                          &ContextPointers);
    00766
    00767         } else {
    00768             SHORT BsFrameSize, TempFrameSize;
    00769
    00770             ControlPc = ContextRecord.BrRp;
    00771             ContextRecord.StIFS = ContextRecord.RsPFS;
    00772             BsFrameSize = (SHORT)(ContextRecord.StIFS >> PFS_SIZE_SHIFT) & PFS_SIZE_MASK;
    00773             TempFrameSize = BsFrameSize - (SHORT)((ContextRecord.RsBSP >> 3) & NAT_BITS_PER_RNAT_REG);
    00774             while (TempFrameSize > 0) {
    00775                 BsFrameSize++;
    00776                 TempFrameSize -= NAT_BITS_PER_RNAT_REG;
    00777             }
    00778             ContextRecord.RsBSP -= BsFrameSize * sizeof(ULONGLONG);
    00779         }
    00780
    00781     } while ((PVOID)ContextRecord.IntSp != TrFrame1);
    00782
    00783     //
    00784     // Process GetThreadContext or SetThreadContext as specified.
    00785     //
    00786
    00787     if (*SystemArgument1 != 0) {
    00788
    00789         //
    00790         // Set Context from proper Context mode
    00791         //
    00792
    00793         PspSetContext(TrFrame1, &ContextPointers, &ContextInfo->Context,
    00794                       ContextInfo->Mode);
    00795
    00796     } else {
    00797
    00798         //
    00799         // Get Context from proper Context mode
    00800         //
    00801
    00802         KiFlushUserRseState(TrFrame1);
    00803         PspGetContext(TrFrame1, &ContextPointers, &ContextInfo->Context);
    00804
    00805     }
    00806
    00807     KeSetEvent(&ContextInfo->OperationComplete, 0, FALSE);
    00808     return;
    00809 }