psarch.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017
  1. /*++
  2. Copyright (c) 2013 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. psarch.c
  9. Abstract:
  10. This module implements architecture specific functionality for the process
  11. and thread library.
  12. Author:
  13. Evan Green 28-Mar-2013
  14. Environment:
  15. Kernel
  16. --*/
  17. //
  18. // ------------------------------------------------------------------- Includes
  19. //
  20. #include <minoca/kernel/kernel.h>
  21. #include <minoca/kernel/x86.h>
  22. #include <minoca/debug/dbgproto.h>
  23. #include "../psp.h"
  24. //
  25. // --------------------------------------------------------------------- Macros
  26. //
  27. //
  28. // This macro returns non-zero if the given segment descriptor is a valid
  29. // user segment selector.
  30. //
  31. #define VALID_USER_SEGMENT(_Segment) \
  32. (((_Segment) & SEGMENT_PRIVILEGE_USER) == SEGMENT_PRIVILEGE_USER)
  33. //
  34. // ---------------------------------------------------------------- Definitions
  35. //
  36. #define X86_INT_INSTRUCTION_PREFIX 0xCD
  37. #define X86_INT_INSTRUCTION_LENGTH 2
  38. #define X86_CALL_INSTRUCTION_LENGTH 5
  39. //
  40. // Define an intial value for the thread pointer, which is a valid user mode
  41. // GDT entry with offset and limit at zero.
  42. //
  43. #define X86_INITIAL_THREAD_POINTER 0x00CFF2000000FFFFULL
  44. //
  45. // ------------------------------------------------------ Data Type Definitions
  46. //
  47. //
  48. // ----------------------------------------------- Internal Function Prototypes
  49. //
  50. KSTATUS
  51. PspIsSysenterTrapFrame (
  52. PTRAP_FRAME TrapFrame,
  53. PBOOL FromSysenter
  54. );
  55. //
  56. // -------------------------------------------------------------------- Globals
  57. //
  58. //
  59. // Define the initial architecture-specific contents of the thread pointer data
  60. // for a newly created thread.
  61. //
  62. const ULONGLONG PsInitialThreadPointer = X86_INITIAL_THREAD_POINTER;
  63. //
  64. // ------------------------------------------------------------------ Functions
  65. //
  66. ULONG
  67. PsDequeuePendingSignal (
  68. PSIGNAL_PARAMETERS SignalParameters,
  69. PTRAP_FRAME TrapFrame
  70. )
  71. /*++
  72. Routine Description:
  73. This routine dequeues the first signal in the thread or process signal mask
  74. of the current thread that is not handled by any default processing.
  75. Arguments:
  76. SignalParameters - Supplies a pointer to a caller-allocated structure where
  77. the signal parameter information might get returned.
  78. TrapFrame - Supplies a pointer to the current trap frame. If this trap frame
  79. is not destined for user mode, this function exits immediately.
  80. Return Value:
  81. Returns a signal number if a signal was queued.
  82. -1 if no signal was dispatched.
  83. --*/
  84. {
  85. BOOL SignalHandled;
  86. ULONG SignalNumber;
  87. //
  88. // If the trap frame is not destined for user mode, then forget it.
  89. //
  90. if (IS_TRAP_FRAME_FROM_PRIVILEGED_MODE(TrapFrame) != FALSE) {
  91. return -1;
  92. }
  93. do {
  94. SignalNumber = PspDequeuePendingSignal(SignalParameters,
  95. TrapFrame,
  96. NULL);
  97. if (SignalNumber == -1) {
  98. break;
  99. }
  100. SignalHandled = PspSignalAttemptDefaultProcessing(SignalNumber);
  101. } while (SignalHandled != FALSE);
  102. return SignalNumber;
  103. }
  104. VOID
  105. PsApplySynchronousSignal (
  106. PTRAP_FRAME TrapFrame,
  107. PSIGNAL_PARAMETERS SignalParameters,
  108. BOOL InSystemCall
  109. )
  110. /*++
  111. Routine Description:
  112. This routine applies the given signal onto the current thread. It is
  113. required that no signal is already in progress, nor will any other signals
  114. be applied for the duration of the system call.
  115. Arguments:
  116. TrapFrame - Supplies a pointer to the current trap frame. This trap frame
  117. must be destined for user mode.
  118. SignalParameters - Supplies a pointer to the signal information to apply.
  119. InSystemCall - Supplies a boolean indicating if the trap frame came from
  120. a system call, in which case this routine will look inside to
  121. potentially prepare restart information.
  122. Return Value:
  123. None.
  124. --*/
  125. {
  126. PSIGNAL_CONTEXT_X86 Context;
  127. UINTN ContextSp;
  128. ULONG Flags;
  129. PSIGNAL_SET RestoreSignals;
  130. BOOL Result;
  131. KSTATUS Status;
  132. INTN SystemCallResult;
  133. PKTHREAD Thread;
  134. Thread = KeGetCurrentThread();
  135. ContextSp = ALIGN_RANGE_DOWN(TrapFrame->Esp - sizeof(SIGNAL_CONTEXT_X86),
  136. FPU_CONTEXT_ALIGNMENT);
  137. Context = (PVOID)ContextSp;
  138. Flags = 0;
  139. Result = MmUserWrite(&(Context->Common.Next), 0);
  140. RestoreSignals = &(Thread->BlockedSignals);
  141. if ((Thread->Flags & THREAD_FLAG_RESTORE_SIGNALS) != 0) {
  142. RestoreSignals = &(Thread->RestoreSignals);
  143. Thread->Flags &= ~THREAD_FLAG_RESTORE_SIGNALS;
  144. }
  145. Status = MmCopyToUserMode(&(Context->Common.Mask),
  146. RestoreSignals,
  147. sizeof(SIGNAL_SET));
  148. //
  149. // TODO: Support alternate signal stacks.
  150. //
  151. Result &= MmUserWrite(&(Context->Common.Stack.Base), 0);
  152. Result &= MmUserWrite(&(Context->Common.Stack.Size), 0);
  153. Result &= MmUserWrite32(&(Context->Common.Stack.Flags), 0);
  154. //
  155. // The trap frame had better be complete or else kernel data might be being
  156. // leaked.
  157. //
  158. ASSERT(ArIsTrapFrameComplete(TrapFrame));
  159. Status |= MmCopyToUserMode(&(Context->TrapFrame),
  160. TrapFrame,
  161. sizeof(TRAP_FRAME));
  162. TrapFrame->Esp = ContextSp;
  163. if ((Thread->FpuFlags & THREAD_FPU_FLAG_IN_USE) != 0) {
  164. Flags |= SIGNAL_CONTEXT_FLAG_FPU_VALID;
  165. if ((Thread->FpuFlags & THREAD_FPU_FLAG_OWNER) != 0) {
  166. ArSaveFpuState(Thread->FpuContext);
  167. }
  168. Status |= MmCopyToUserMode(&(Context->FpuContext),
  169. Thread->FpuContext,
  170. sizeof(FPU_CONTEXT));
  171. }
  172. //
  173. // If this signal is being applied in the middle of a system call, the trap
  174. // frame needs modification if it is restartable. EAX holds the system call
  175. // result.
  176. //
  177. SystemCallResult = (INTN)TrapFrame->Eax;
  178. if ((InSystemCall != FALSE) &&
  179. (IS_SYSTEM_CALL_NUMBER_RESTARTABLE(Context->TrapFrame.Ecx)) &&
  180. (IS_SYSTEM_CALL_RESULT_RESTARTABLE(SystemCallResult) != FALSE)) {
  181. //
  182. // If the result indicates that the system call is restartable after a
  183. // signal is applied, then let user mode know by setting the restart
  184. // flag in the context.
  185. //
  186. if (IS_SYSTEM_CALL_RESULT_RESTARTABLE_AFTER_SIGNAL(SystemCallResult)) {
  187. Flags |= SIGNAL_CONTEXT_FLAG_RESTART;
  188. }
  189. //
  190. // In case the handler does not allow restarts, convert the saved
  191. // restart status to the interrupted status.
  192. //
  193. MmUserWrite(&(Context->TrapFrame.Eax), STATUS_INTERRUPTED);
  194. }
  195. Result &= MmUserWrite32(&(Context->Common.Flags), Flags);
  196. TrapFrame->Esp -= sizeof(SIGNAL_PARAMETERS);
  197. Status |= MmCopyToUserMode((PVOID)(TrapFrame->Esp),
  198. SignalParameters,
  199. sizeof(SIGNAL_PARAMETERS));
  200. if ((Status != STATUS_SUCCESS) || (Result == FALSE)) {
  201. PsHandleUserModeFault((PVOID)(TrapFrame->Esp),
  202. FAULT_FLAG_WRITE | FAULT_FLAG_PAGE_NOT_PRESENT,
  203. TrapFrame,
  204. Thread->OwningProcess);
  205. PsApplyPendingSignals(TrapFrame);
  206. }
  207. TrapFrame->Eip = (ULONG)(Thread->OwningProcess->SignalHandlerRoutine);
  208. TrapFrame->Eflags &= ~IA32_EFLAG_TF;
  209. ADD_SIGNAL(Thread->BlockedSignals, SignalParameters->SignalNumber);
  210. return;
  211. }
  212. INTN
  213. PspRestorePreSignalTrapFrame (
  214. PTRAP_FRAME TrapFrame,
  215. PSIGNAL_CONTEXT UserContext
  216. )
  217. /*++
  218. Routine Description:
  219. This routine restores the original user mode thread context for the thread
  220. before a signal was invoked.
  221. Arguments:
  222. TrapFrame - Supplies a pointer to the trap frame from this system call.
  223. UserContext - Supplies the user context to restore.
  224. Return Value:
  225. Returns the architecture-specific return register from the thread context.
  226. --*/
  227. {
  228. PSIGNAL_CONTEXT_X86 Context;
  229. ULONG Eflags;
  230. ULONG Flags;
  231. TRAP_FRAME Frame;
  232. BOOL FromSysenter;
  233. SIGNAL_SET SignalMask;
  234. KSTATUS Status;
  235. PKTHREAD Thread;
  236. Context = (PSIGNAL_CONTEXT_X86)UserContext;
  237. Thread = KeGetCurrentThread();
  238. Status = MmCopyFromUserMode(&Frame,
  239. &(Context->TrapFrame),
  240. sizeof(TRAP_FRAME));
  241. Status |= MmCopyFromUserMode(&SignalMask,
  242. &(Context->Common.Mask),
  243. sizeof(SIGNAL_SET));
  244. if (!MmUserRead(&(UserContext->Flags), &Flags)) {
  245. Status = STATUS_ACCESS_VIOLATION;
  246. }
  247. if (!KSUCCESS(Status)) {
  248. goto RestorePreSignalTrapFrameEnd;
  249. }
  250. PsSetSignalMask(&SignalMask, NULL);
  251. //
  252. // Sanitize EFLAGS, ES, and DS. Then copy the whole trap frame.
  253. //
  254. Eflags = TrapFrame->Eflags & ~IA32_EFLAG_USER;
  255. Frame.Eflags = (Frame.Eflags & IA32_EFLAG_USER) | Eflags;
  256. Frame.Ds = USER_DS;
  257. Frame.Es = USER_DS;
  258. RtlCopyMemory(TrapFrame, &Frame, sizeof(TRAP_FRAME));
  259. if (((Flags & SIGNAL_CONTEXT_FLAG_FPU_VALID) != 0) &&
  260. (Thread->FpuContext != NULL)) {
  261. Status = MmCopyFromUserMode(Thread->FpuContext,
  262. &(Context->FpuContext),
  263. sizeof(FPU_CONTEXT));
  264. if (!KSUCCESS(Status)) {
  265. goto RestorePreSignalTrapFrameEnd;
  266. }
  267. Thread->FpuFlags |= THREAD_FPU_FLAG_IN_USE;
  268. if ((Thread->FpuFlags & THREAD_FPU_FLAG_OWNER) != 0) {
  269. ArDisableFpu();
  270. Thread->FpuFlags &= ~THREAD_FPU_FLAG_OWNER;
  271. }
  272. }
  273. //
  274. // If the signal context indicates that a system call restart is necessary,
  275. // then back up EIP so that the system call gets executed again when the
  276. // trap frame gets restored.
  277. //
  278. if ((Flags & SIGNAL_CONTEXT_FLAG_RESTART) != 0) {
  279. Status = PspIsSysenterTrapFrame(TrapFrame, &FromSysenter);
  280. if (!KSUCCESS(Status)) {
  281. goto RestorePreSignalTrapFrameEnd;
  282. }
  283. //
  284. // If the saved trap frame was from a full system call (not sysenter),
  285. // only back up over the INT instruction. When the signal was applied,
  286. // the system call number and parameter were stored in ECX and EDX.
  287. //
  288. if (FromSysenter == FALSE) {
  289. TrapFrame->Eip -= X86_INT_INSTRUCTION_LENGTH;
  290. //
  291. // On sysenter trap frames, EIP points to the instruction after the
  292. // dummy call to OspSysenter. Back up over that, which will replay
  293. // setting up the arguments for sysenter.
  294. //
  295. } else {
  296. TrapFrame->Eip -= X86_CALL_INSTRUCTION_LENGTH;
  297. }
  298. }
  299. RestorePreSignalTrapFrameEnd:
  300. if (!KSUCCESS(Status)) {
  301. PsSignalThread(Thread, SIGNAL_ACCESS_VIOLATION, NULL, TRUE);
  302. }
  303. //
  304. // Preserve EAX by returning it. The system call assembly return path
  305. // guarantees this.
  306. //
  307. return (INTN)TrapFrame->Eax;
  308. }
  309. VOID
  310. PspArchRestartSystemCall (
  311. PTRAP_FRAME TrapFrame
  312. )
  313. /*++
  314. Routine Description:
  315. This routine determines whether or not a system call needs to be restarted.
  316. If so, it modifies the given trap frame such that the system call return
  317. to user mode will fall right back into calling the system call.
  318. Arguments:
  319. TrapFrame - Supplies a pointer to the full trap frame saved by a system
  320. call in order to attempt dispatching a signal.
  321. Return Value:
  322. None.
  323. --*/
  324. {
  325. BOOL FromSysenter;
  326. KSTATUS Status;
  327. //
  328. // On x86, the trap frame holds the system call return value in EAX. Check
  329. // to see if the system call can be restarted. If not, exit.
  330. //
  331. if (!IS_SYSTEM_CALL_NUMBER_RESTARTABLE(TrapFrame->Ecx) ||
  332. !IS_SYSTEM_CALL_RESULT_RESTARTABLE_NO_SIGNAL((INTN)TrapFrame->Eax)) {
  333. return;
  334. }
  335. //
  336. // Attempt to determine if this trap frame was created by sysenter. If this
  337. // fails, then signal the thread and dispatch the new signal. This restart
  338. // call is likely already in the middle of dispatching signals and found
  339. // there were none.
  340. //
  341. Status = PspIsSysenterTrapFrame(TrapFrame, &FromSysenter);
  342. if (!KSUCCESS(Status)) {
  343. PsSignalThread(KeGetCurrentThread(),
  344. SIGNAL_ACCESS_VIOLATION,
  345. NULL,
  346. TRUE);
  347. PsApplyPendingSignals(TrapFrame);
  348. return;
  349. }
  350. //
  351. // If the trap frame was from a full system call (not sysenter), only back
  352. // up over the INT instruction.
  353. //
  354. if (FromSysenter == FALSE) {
  355. TrapFrame->Eip -= X86_INT_INSTRUCTION_LENGTH;
  356. //
  357. // A sysenter trap frame's EIP points to the instruction after the dummy
  358. // call to OspSysenter. Back up over that.
  359. //
  360. } else {
  361. TrapFrame->Eip -= X86_CALL_INSTRUCTION_LENGTH;
  362. }
  363. return;
  364. }
  365. VOID
  366. PspPrepareThreadForFirstRun (
  367. PKTHREAD Thread,
  368. PTRAP_FRAME TrapFrame,
  369. BOOL ParameterIsStack
  370. )
  371. /*++
  372. Routine Description:
  373. This routine performs any architecture specific initialization to prepare a
  374. thread for being context swapped for the first time.
  375. Arguments:
  376. Thread - Supplies a pointer to the thread being prepared for its first run.
  377. TrapFrame - Supplies an optional pointer for the thread to restore on its
  378. first run.
  379. ParameterIsStack - Supplies a boolean indicating whether the thread
  380. parameter is the value that should be used as the initial stack pointer.
  381. Return Value:
  382. None.
  383. --*/
  384. {
  385. ULONG CodeSelector;
  386. ULONG DataSelector;
  387. ULONG Eip;
  388. ULONG Fs;
  389. PUINTN StackPointer;
  390. PTRAP_FRAME StackTrapFrame;
  391. UINTN TrapStackPointer;
  392. PUINTN UserStackPointer;
  393. TrapStackPointer = (UINTN)Thread->KernelStack + Thread->KernelStackSize -
  394. sizeof(PVOID);
  395. StackPointer = (PUINTN)TrapStackPointer;
  396. //
  397. // Determine the appropriate value for the flags, code selector, and entry
  398. // point.
  399. //
  400. if ((Thread->Flags & THREAD_FLAG_USER_MODE) != 0) {
  401. ASSERT((TrapFrame == NULL) || (ParameterIsStack == FALSE));
  402. //
  403. // Set up the values on the user mode stack. Push the parameter and a
  404. // dummy return address.
  405. //
  406. if (TrapFrame == NULL) {
  407. if (ParameterIsStack != FALSE) {
  408. UserStackPointer = Thread->ThreadParameter - sizeof(PVOID);
  409. ASSERT(((PVOID)UserStackPointer >= Thread->UserStack) &&
  410. ((PVOID)UserStackPointer <
  411. Thread->UserStack + Thread->UserStackSize));
  412. } else {
  413. UserStackPointer = Thread->UserStack + Thread->UserStackSize -
  414. sizeof(PVOID);
  415. }
  416. MmUserWrite(UserStackPointer, (UINTN)Thread->ThreadParameter);
  417. UserStackPointer -= 1;
  418. MmUserWrite(UserStackPointer, 0);
  419. TrapStackPointer = (UINTN)UserStackPointer;
  420. }
  421. //
  422. // Set the variables that will be used to set up the kernel stack.
  423. //
  424. CodeSelector = USER32_CS;
  425. DataSelector = USER_DS;
  426. Eip = (UINTN)Thread->ThreadRoutine;
  427. Fs = DataSelector;
  428. //
  429. // Make room for SS ESP (in that order), as they're part of the
  430. // hardware trap frame when returning to user mode. Don't worry about
  431. // filling them out, the restore trap frame function will handle that.
  432. //
  433. StackPointer -= 2;
  434. } else {
  435. CodeSelector = KERNEL_CS;
  436. DataSelector = KERNEL_DS;
  437. Fs = GDT_PROCESSOR;
  438. Eip = (UINTN)PspKernelThreadStart;
  439. }
  440. //
  441. // Make room for Eflags, CS, and EIP, and a dummy error code expected by the
  442. // restore trap frame code.
  443. //
  444. StackPointer -= 4;
  445. //
  446. // Make room for a trap frame to be restored.
  447. //
  448. StackPointer = (PUINTN)((PUCHAR)StackPointer - sizeof(TRAP_FRAME));
  449. StackTrapFrame = (PTRAP_FRAME)StackPointer;
  450. if (TrapFrame != NULL) {
  451. if (ArIsTrapFrameComplete(TrapFrame) != FALSE) {
  452. RtlCopyMemory(StackTrapFrame, TrapFrame, sizeof(TRAP_FRAME));
  453. //
  454. // Return a process ID of 0 to the child on fork.
  455. //
  456. StackTrapFrame->Eax = 0;
  457. } else {
  458. //
  459. // User mode tried to pull a fast one by forking with the fast
  460. // system call handler path. Joke's on them; zero out the registers
  461. // that didn't get saved.
  462. //
  463. RtlZeroMemory(StackTrapFrame, sizeof(TRAP_FRAME));
  464. StackTrapFrame->Eip = TrapFrame->Eip;
  465. StackTrapFrame->Esp = TrapFrame->Esp;
  466. }
  467. } else {
  468. RtlZeroMemory(StackTrapFrame, sizeof(TRAP_FRAME));
  469. StackTrapFrame->Eip = Eip;
  470. StackTrapFrame->Esp = TrapStackPointer;
  471. StackTrapFrame->Ecx = (UINTN)Thread->ThreadParameter;
  472. }
  473. StackTrapFrame->Ds = DataSelector;
  474. StackTrapFrame->Es = DataSelector;
  475. StackTrapFrame->Fs = Fs;
  476. StackTrapFrame->Gs = GDT_THREAD;
  477. StackTrapFrame->Ss = DataSelector;
  478. StackTrapFrame->Cs = CodeSelector;
  479. StackTrapFrame->Eflags = IA32_EFLAG_ALWAYS_1 | IA32_EFLAG_IF;
  480. Thread->KernelStackPointer = StackPointer;
  481. return;
  482. }
  483. INTN
  484. PspArchResetThreadContext (
  485. PKTHREAD Thread,
  486. PTRAP_FRAME TrapFrame
  487. )
  488. /*++
  489. Routine Description:
  490. This routine sets up the given trap frame as if the user mode portion of
  491. the thread was running for the first time.
  492. Arguments:
  493. Thread - Supplies a pointer to the thread being reset.
  494. TrapFrame - Supplies a pointer where the initial thread's trap frame will
  495. be returned.
  496. Return Value:
  497. The value that the thread should return when exiting back to user mode.
  498. --*/
  499. {
  500. PUINTN UserStackPointer;
  501. Thread->ThreadPointer = PsInitialThreadPointer;
  502. UserStackPointer = Thread->ThreadParameter - sizeof(PVOID);
  503. ASSERT(((PVOID)UserStackPointer >= Thread->UserStack) &&
  504. ((PVOID)UserStackPointer <
  505. Thread->UserStack + Thread->UserStackSize));
  506. MmUserWrite(UserStackPointer, (UINTN)(Thread->ThreadParameter));
  507. UserStackPointer -= 1;
  508. MmUserWrite(UserStackPointer, 0);
  509. RtlZeroMemory(TrapFrame, sizeof(TRAP_FRAME));
  510. TrapFrame->Cs = USER32_CS;
  511. TrapFrame->Ds = USER_DS;
  512. TrapFrame->Es = USER_DS;
  513. TrapFrame->Fs = USER_DS;
  514. TrapFrame->Gs = GDT_THREAD;
  515. TrapFrame->Ss = USER_DS;
  516. TrapFrame->Eip = (UINTN)Thread->ThreadRoutine;
  517. TrapFrame->Eflags = IA32_EFLAG_ALWAYS_1 | IA32_EFLAG_IF;
  518. TrapFrame->Esp = (UINTN)UserStackPointer;
  519. TrapFrame->Ecx = (UINTN)Thread->ThreadParameter;
  520. if ((Thread->FpuFlags & THREAD_FPU_FLAG_IN_USE) != 0) {
  521. Thread->FpuFlags &= ~(THREAD_FPU_FLAG_IN_USE | THREAD_FPU_FLAG_OWNER);
  522. ArDisableFpu();
  523. }
  524. //
  525. // Return 0 as this will make its way to EAX when the system call returns.
  526. //
  527. return 0;
  528. }
  529. KSTATUS
  530. PspArchCloneThread (
  531. PKTHREAD OldThread,
  532. PKTHREAD NewThread
  533. )
  534. /*++
  535. Routine Description:
  536. This routine performs architecture specific operations upon cloning a
  537. thread.
  538. Arguments:
  539. OldThread - Supplies a pointer to the thread being copied.
  540. NewThread - Supplies a pointer to the newly created thread.
  541. Return Value:
  542. Status code.
  543. --*/
  544. {
  545. return STATUS_SUCCESS;
  546. }
  547. KSTATUS
  548. PspArchGetDebugBreakInformation (
  549. PTRAP_FRAME TrapFrame
  550. )
  551. /*++
  552. Routine Description:
  553. This routine gets the current debug break information.
  554. Arguments:
  555. TrapFrame - Supplies a pointer to the user mode trap frame that caused the
  556. break.
  557. Return Value:
  558. Status code.
  559. --*/
  560. {
  561. PBREAK_NOTIFICATION Break;
  562. PPROCESS_DEBUG_DATA DebugData;
  563. PKPROCESS Process;
  564. PKTHREAD Thread;
  565. Thread = KeGetCurrentThread();
  566. Process = Thread->OwningProcess;
  567. DebugData = Process->DebugData;
  568. ASSERT(DebugData != NULL);
  569. ASSERT(DebugData->DebugLeaderThread == Thread);
  570. ASSERT(DebugData->DebugCommand.Command == DebugCommandGetBreakInformation);
  571. ASSERT(DebugData->DebugCommand.Size == sizeof(BREAK_NOTIFICATION));
  572. Break = DebugData->DebugCommand.Data;
  573. Break->Exception = ExceptionSignal;
  574. Break->ProcessorOrThreadNumber = Thread->ThreadId;
  575. Break->ProcessorOrThreadCount = Process->ThreadCount;
  576. Break->Process = Process->Identifiers.ProcessId;
  577. Break->ProcessorBlock = (UINTN)NULL;
  578. Break->LoadedModuleCount = Process->ImageCount;
  579. Break->LoadedModuleSignature = Process->ImageListSignature;
  580. //
  581. // Be careful. A trap frame that resulted from a sysenter (before becoming
  582. // complete for signal dispatching) only contains EIP and ESP. The rest is
  583. // just garbage from the kernel mode stack, which shouldn't be leaked to
  584. // the debugger.
  585. //
  586. Break->InstructionPointer = TrapFrame->Eip;
  587. RtlZeroMemory(Break->InstructionStream, sizeof(Break->InstructionStream));
  588. MmCopyFromUserMode(Break->InstructionStream,
  589. (PVOID)TrapFrame->Eip,
  590. sizeof(Break->InstructionStream));
  591. Break->Registers.X86.Eip = TrapFrame->Eip;
  592. Break->Registers.X86.Esp = TrapFrame->Esp;
  593. Break->Registers.X86.Ecx = TrapFrame->Ecx;
  594. Break->Registers.X86.Edx = TrapFrame->Edx;
  595. if (ArIsTrapFrameComplete(TrapFrame) != FALSE) {
  596. Break->ErrorCode = TrapFrame->ErrorCode;
  597. Break->Registers.X86.Eax = TrapFrame->Eax;
  598. Break->Registers.X86.Ebx = TrapFrame->Ebx;
  599. Break->Registers.X86.Ebp = TrapFrame->Ebp;
  600. Break->Registers.X86.Esi = TrapFrame->Esi;
  601. Break->Registers.X86.Edi = TrapFrame->Edi;
  602. Break->Registers.X86.Eflags = TrapFrame->Eflags;
  603. Break->Registers.X86.Cs = TrapFrame->Cs;
  604. Break->Registers.X86.Ds = TrapFrame->Ds;
  605. Break->Registers.X86.Es = TrapFrame->Es;
  606. Break->Registers.X86.Fs = TrapFrame->Fs;
  607. Break->Registers.X86.Gs = TrapFrame->Gs;
  608. Break->Registers.X86.Ss = TrapFrame->Ss;
  609. } else {
  610. Break->ErrorCode = 0;
  611. Break->Registers.X86.Eax = 0;
  612. Break->Registers.X86.Ebx = 0;
  613. Break->Registers.X86.Ebp = 0;
  614. Break->Registers.X86.Esi = 0;
  615. Break->Registers.X86.Edi = 0;
  616. Break->Registers.X86.Eflags = 0;
  617. Break->Registers.X86.Cs = USER32_CS;
  618. Break->Registers.X86.Ds = USER_DS;
  619. Break->Registers.X86.Es = USER_DS;
  620. Break->Registers.X86.Fs = GDT_THREAD;
  621. Break->Registers.X86.Gs = GDT_THREAD;
  622. Break->Registers.X86.Ss = USER_DS;
  623. }
  624. return STATUS_SUCCESS;
  625. }
  626. KSTATUS
  627. PspArchSetDebugBreakInformation (
  628. PTRAP_FRAME TrapFrame
  629. )
  630. /*++
  631. Routine Description:
  632. This routine sets the current debug break information, mostly just the
  633. register.
  634. Arguments:
  635. TrapFrame - Supplies a pointer to the user mode trap frame that caused the
  636. break.
  637. Return Value:
  638. Status code.
  639. --*/
  640. {
  641. PBREAK_NOTIFICATION Break;
  642. PPROCESS_DEBUG_DATA DebugData;
  643. PKPROCESS Process;
  644. PKTHREAD Thread;
  645. Thread = KeGetCurrentThread();
  646. Process = Thread->OwningProcess;
  647. DebugData = Process->DebugData;
  648. ASSERT(DebugData != NULL);
  649. ASSERT(DebugData->DebugLeaderThread == Thread);
  650. ASSERT(DebugData->DebugCommand.Command == DebugCommandSetBreakInformation);
  651. ASSERT(DebugData->DebugCommand.Size == sizeof(BREAK_NOTIFICATION));
  652. Break = DebugData->DebugCommand.Data;
  653. if ((!VALID_USER_SEGMENT(Break->Registers.X86.Cs)) ||
  654. (!VALID_USER_SEGMENT(Break->Registers.X86.Ds)) ||
  655. (!VALID_USER_SEGMENT(Break->Registers.X86.Es)) ||
  656. (!VALID_USER_SEGMENT(Break->Registers.X86.Fs)) ||
  657. (!VALID_USER_SEGMENT(Break->Registers.X86.Gs)) ||
  658. (!VALID_USER_SEGMENT(Break->Registers.X86.Ss))) {
  659. return STATUS_INVALID_PARAMETER;
  660. }
  661. TrapFrame->Eax = Break->Registers.X86.Eax;
  662. TrapFrame->Ebx = Break->Registers.X86.Ebx;
  663. TrapFrame->Ecx = Break->Registers.X86.Ecx;
  664. TrapFrame->Edx = Break->Registers.X86.Edx;
  665. TrapFrame->Ebp = Break->Registers.X86.Ebp;
  666. TrapFrame->Esp = Break->Registers.X86.Esp;
  667. TrapFrame->Esi = Break->Registers.X86.Esi;
  668. TrapFrame->Edi = Break->Registers.X86.Edi;
  669. TrapFrame->Eip = Break->Registers.X86.Eip;
  670. TrapFrame->Eflags = Break->Registers.X86.Eflags |
  671. IA32_EFLAG_ALWAYS_1 | IA32_EFLAG_IF;
  672. TrapFrame->Cs = Break->Registers.X86.Cs | SEGMENT_PRIVILEGE_USER;
  673. TrapFrame->Ds = Break->Registers.X86.Ds | SEGMENT_PRIVILEGE_USER;
  674. TrapFrame->Es = Break->Registers.X86.Es | SEGMENT_PRIVILEGE_USER;
  675. TrapFrame->Fs = Break->Registers.X86.Fs | SEGMENT_PRIVILEGE_USER;
  676. TrapFrame->Gs = Break->Registers.X86.Gs | SEGMENT_PRIVILEGE_USER;
  677. TrapFrame->Ss = Break->Registers.X86.Ss | SEGMENT_PRIVILEGE_USER;
  678. return STATUS_SUCCESS;
  679. }
  680. KSTATUS
  681. PspArchSetOrClearSingleStep (
  682. PTRAP_FRAME TrapFrame,
  683. BOOL Set
  684. )
  685. /*++
  686. Routine Description:
  687. This routine sets the current thread into single step mode.
  688. Arguments:
  689. TrapFrame - Supplies a pointer to the user mode trap frame that caused the
  690. break.
  691. Set - Supplies a boolean indicating whether to set single step mode (TRUE)
  692. or clear single step mode (FALSE).
  693. Return Value:
  694. Status code.
  695. --*/
  696. {
  697. PKPROCESS Process;
  698. Process = PsGetCurrentProcess();
  699. ASSERT(Process != PsGetKernelProcess());
  700. ASSERT(IS_TRAP_FRAME_FROM_PRIVILEGED_MODE(TrapFrame) == FALSE);
  701. if (Set != FALSE) {
  702. TrapFrame->Eflags |= IA32_EFLAG_TF;
  703. } else {
  704. TrapFrame->Eflags &= ~IA32_EFLAG_TF;
  705. }
  706. return STATUS_SUCCESS;
  707. }
  708. //
  709. // --------------------------------------------------------- Internal Functions
  710. //
  711. KSTATUS
  712. PspIsSysenterTrapFrame (
  713. PTRAP_FRAME TrapFrame,
  714. PBOOL FromSysenter
  715. )
  716. /*++
  717. Routine Description:
  718. This routine determines whether or not the given trap frame was created by
  719. sysenter.
  720. Arguments:
  721. TrapFrame - Supplies a pointer to the trap frame whose origin is in
  722. question.
  723. FromSysenter - Supplies a pointer to a boolean that receives whether or not
  724. the trap frame came from sysenter.
  725. Return Value:
  726. TRUE if the trap frame was created by sysenter. FALSE otherwise.
  727. --*/
  728. {
  729. UCHAR Instruction;
  730. PVOID PreviousInstructionPointer;
  731. BOOL Result;
  732. ASSERT(IS_TRAP_FRAME_FROM_PRIVILEGED_MODE(TrapFrame) == FALSE);
  733. PreviousInstructionPointer = (PVOID)TrapFrame->Eip -
  734. X86_INT_INSTRUCTION_LENGTH;
  735. Result = MmUserRead8(PreviousInstructionPointer, &Instruction);
  736. if (Result == FALSE) {
  737. return STATUS_ACCESS_VIOLATION;
  738. }
  739. *FromSysenter = FALSE;
  740. if (Instruction != X86_INT_INSTRUCTION_PREFIX) {
  741. *FromSysenter = TRUE;
  742. }
  743. return STATUS_SUCCESS;
  744. }