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 #ifdef CONFIG_SMP 143 /* Do the swap at SYNCH_LEVEL */ 144 KfRaiseIrql(SYNCH_LEVEL); 145 #endif 146 147 /* Switch away from the idle thread */ 148 KiSwapContext(APC_LEVEL, OldThread); 149 150 #ifdef CONFIG_SMP 151 /* Go back to DISPATCH_LEVEL */ 152 KeLowerIrql(DISPATCH_LEVEL); 153 #endif 154 } 155 else 156 { 157 /* Continue staying idle. Note the HAL returns with interrupts on */ 158 Prcb->PowerState.IdleFunction(&Prcb->PowerState); 159 } 160 } 161 } 162 163 VOID 164 NTAPI 165 KiSwapProcess(IN PKPROCESS NewProcess, 166 IN PKPROCESS OldProcess) 167 { 168 PKIPCR Pcr = (PKIPCR)KeGetPcr(); 169 170 #ifdef CONFIG_SMP 171 /* Update active processor mask */ 172 InterlockedXor64((PLONG64)&NewProcess->ActiveProcessors, Pcr->Prcb.SetMember); 173 InterlockedXor64((PLONG64)&OldProcess->ActiveProcessors, Pcr->Prcb.SetMember); 174 #endif 175 176 /* Update CR3 */ 177 __writecr3(NewProcess->DirectoryTableBase[0]); 178 179 /* Update IOPM offset */ 180 Pcr->TssBase->IoMapBase = NewProcess->IopmOffset; 181 } 182 183 NTSTATUS 184 NTAPI 185 NtSetLdtEntries(ULONG Selector1, LDT_ENTRY LdtEntry1, ULONG Selector2, LDT_ENTRY LdtEntry2) 186 { 187 UNIMPLEMENTED; 188 __debugbreak(); 189 return STATUS_UNSUCCESSFUL; 190 } 191 192 NTSTATUS 193 NTAPI 194 NtVdmControl(IN ULONG ControlCode, 195 IN PVOID ControlData) 196 { 197 /* Not supported */ 198 return STATUS_NOT_IMPLEMENTED; 199 } 200