1 /* 2 * PROJECT: ReactOS Kernel 3 * LICENSE: GPL - See COPYING in the top level directory 4 * PURPOSE: stubs 5 * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org) 6 */ 7 8 /* INCLUDES ******************************************************************/ 9 10 #include <ntoskrnl.h> 11 12 #define NDEBUG 13 #include <debug.h> 14 15 /* GLOBALS *******************************************************************/ 16 17 ULONG ProcessCount; 18 SIZE_T KeXStateLength = sizeof(XSAVE_FORMAT); 19 20 PVOID 21 KiSwitchKernelStackHelper( 22 LONG_PTR StackOffset, 23 PVOID OldStackBase); 24 25 /* 26 * Kernel stack layout (example pointers): 27 * 0xFFFFFC0F'2D008000 KTHREAD::StackBase 28 * [XSAVE_AREA size == KeXStateLength = 0x440] 29 * 0xFFFFFC0F'2D007BC0 KTHREAD::StateSaveArea _XSAVE_FORMAT 30 * 0xFFFFFC0F'2D007B90 KTHREAD::InitialStack 31 * [0x190 bytes KTRAP_FRAME] 32 * 0xFFFFFC0F'2D007A00 KTHREAD::TrapFrame 33 * [KSTART_FRAME] or ... 34 * [KSWITCH_FRAME] 35 * 0xFFFFFC0F'2D007230 KTHREAD::KernelStack 36 */ 37 38 PVOID 39 NTAPI 40 KiSwitchKernelStack(PVOID StackBase, PVOID StackLimit) 41 { 42 PKTHREAD CurrentThread; 43 PVOID OldStackBase; 44 LONG_PTR StackOffset; 45 SIZE_T StackSize; 46 PKIPCR Pcr; 47 ULONG Eflags; 48 49 /* Get the current thread */ 50 CurrentThread = KeGetCurrentThread(); 51 52 /* Save the old stack base */ 53 OldStackBase = CurrentThread->StackBase; 54 55 /* Get the size of the current stack */ 56 StackSize = (ULONG_PTR)CurrentThread->StackBase - CurrentThread->StackLimit; 57 ASSERT(StackSize <= (ULONG_PTR)StackBase - (ULONG_PTR)StackLimit); 58 59 /* Copy the current stack contents to the new stack */ 60 RtlCopyMemory((PUCHAR)StackBase - StackSize, 61 (PVOID)CurrentThread->StackLimit, 62 StackSize); 63 64 /* Calculate the offset between the old and the new stack */ 65 StackOffset = (PUCHAR)StackBase - (PUCHAR)CurrentThread->StackBase; 66 67 /* Disable interrupts while messing with the stack */ 68 Eflags = __readeflags(); 69 _disable(); 70 71 /* Set the new trap frame */ 72 CurrentThread->TrapFrame = (PKTRAP_FRAME)Add2Ptr(CurrentThread->TrapFrame, 73 StackOffset); 74 75 /* Set the new initial stack */ 76 CurrentThread->InitialStack = Add2Ptr(CurrentThread->InitialStack, 77 StackOffset); 78 79 /* Set the new stack limits */ 80 CurrentThread->StackBase = StackBase; 81 CurrentThread->StackLimit = (ULONG_PTR)StackLimit; 82 CurrentThread->LargeStack = TRUE; 83 84 /* Adjust RspBase in the PCR */ 85 Pcr = (PKIPCR)KeGetPcr(); 86 Pcr->Prcb.RspBase += StackOffset; 87 88 /* Adjust Rsp0 in the TSS */ 89 Pcr->TssBase->Rsp0 += StackOffset; 90 91 /* Restore interrupts */ 92 __writeeflags(Eflags); 93 94 return OldStackBase; 95 } 96 97 DECLSPEC_NORETURN 98 VOID 99 KiIdleLoop(VOID) 100 { 101 PKPRCB Prcb = KeGetCurrentPrcb(); 102 PKTHREAD OldThread, NewThread; 103 104 /* Now loop forever */ 105 while (TRUE) 106 { 107 /* Start of the idle loop: disable interrupts */ 108 _enable(); 109 YieldProcessor(); 110 YieldProcessor(); 111 _disable(); 112 113 /* Check for pending timers, pending DPCs, or pending ready threads */ 114 if ((Prcb->DpcData[0].DpcQueueDepth) || 115 (Prcb->TimerRequest) || 116 (Prcb->DeferredReadyListHead.Next)) 117 { 118 /* Quiesce the DPC software interrupt */ 119 HalClearSoftwareInterrupt(DISPATCH_LEVEL); 120 121 /* Handle it */ 122 KiRetireDpcList(Prcb); 123 } 124 125 /* Check if a new thread is scheduled for execution */ 126 if (Prcb->NextThread) 127 { 128 /* Enable interrupts */ 129 _enable(); 130 131 /* Capture current thread data */ 132 OldThread = Prcb->CurrentThread; 133 NewThread = Prcb->NextThread; 134 135 /* Set new thread data */ 136 Prcb->NextThread = NULL; 137 Prcb->CurrentThread = NewThread; 138 139 /* The thread is now running */ 140 NewThread->State = Running; 141 142 /* Do the swap at SYNCH_LEVEL */ 143 KfRaiseIrql(SYNCH_LEVEL); 144 145 /* Switch away from the idle thread */ 146 KiSwapContext(APC_LEVEL, OldThread); 147 148 /* Go back to DISPATCH_LEVEL */ 149 KeLowerIrql(DISPATCH_LEVEL); 150 } 151 else 152 { 153 /* Continue staying idle. Note the HAL returns with interrupts on */ 154 Prcb->PowerState.IdleFunction(&Prcb->PowerState); 155 } 156 } 157 } 158 159 VOID 160 NTAPI 161 KiSwapProcess(IN PKPROCESS NewProcess, 162 IN PKPROCESS OldProcess) 163 { 164 PKIPCR Pcr = (PKIPCR)KeGetPcr(); 165 166 #ifdef CONFIG_SMP 167 /* Update active processor mask */ 168 InterlockedXor64((PLONG64)&NewProcess->ActiveProcessors, Pcr->Prcb.SetMember); 169 InterlockedXor64((PLONG64)&OldProcess->ActiveProcessors, Pcr->Prcb.SetMember); 170 #endif 171 172 /* Update CR3 */ 173 __writecr3(NewProcess->DirectoryTableBase[0]); 174 175 /* Update IOPM offset */ 176 Pcr->TssBase->IoMapBase = NewProcess->IopmOffset; 177 } 178 179 NTSTATUS 180 NTAPI 181 NtSetLdtEntries(ULONG Selector1, LDT_ENTRY LdtEntry1, ULONG Selector2, LDT_ENTRY LdtEntry2) 182 { 183 UNIMPLEMENTED; 184 __debugbreak(); 185 return STATUS_UNSUCCESSFUL; 186 } 187 188 NTSTATUS 189 NTAPI 190 NtVdmControl(IN ULONG ControlCode, 191 IN PVOID ControlData) 192 { 193 /* Not supported */ 194 return STATUS_NOT_IMPLEMENTED; 195 } 196