Compare commits

78 Commits

Author SHA1 Message Date
f79c9023d8 Initialize thread service table
All checks were successful
Builds / ExectOS (amd64, debug) (push) Successful in 29s
Builds / ExectOS (amd64, release) (push) Successful in 37s
Builds / ExectOS (i686, release) (push) Successful in 28s
Builds / ExectOS (i686, debug) (push) Successful in 37s
2026-06-12 23:19:05 +02:00
97703c7932 Add stub for System Service Descriptor Table accessor routine
All checks were successful
Builds / ExectOS (amd64, debug) (push) Successful in 29s
Builds / ExectOS (i686, debug) (push) Successful in 28s
Builds / ExectOS (amd64, release) (push) Successful in 38s
Builds / ExectOS (i686, release) (push) Successful in 37s
2026-06-12 23:16:20 +02:00
2f5902119d Update thread initialization code
All checks were successful
Builds / ExectOS (i686, debug) (push) Successful in 39s
Builds / ExectOS (amd64, debug) (push) Successful in 40s
Builds / ExectOS (amd64, release) (push) Successful in 33s
Builds / ExectOS (i686, release) (push) Successful in 33s
2026-06-12 20:52:23 +02:00
7a10135731 Replace jmp with call to maintain ABI stack alignment
All checks were successful
Builds / ExectOS (amd64, debug) (push) Successful in 25s
Builds / ExectOS (amd64, release) (push) Successful in 30s
Builds / ExectOS (i686, debug) (push) Successful in 29s
Builds / ExectOS (i686, release) (push) Successful in 33s
2026-06-12 15:58:42 +02:00
b0074637f8 Remove hardcoded shift in SIPI vector calculation
All checks were successful
Builds / ExectOS (amd64, release) (push) Successful in 30s
Builds / ExectOS (amd64, debug) (push) Successful in 31s
Builds / ExectOS (i686, debug) (push) Successful in 29s
Builds / ExectOS (i686, release) (push) Successful in 35s
2026-06-12 14:21:27 +02:00
1a062ca05f Trigger low memory allocation before PFN database initialization
All checks were successful
Builds / ExectOS (i686, debug) (push) Successful in 30s
Builds / ExectOS (amd64, debug) (push) Successful in 32s
Builds / ExectOS (amd64, release) (push) Successful in 39s
Builds / ExectOS (i686, release) (push) Successful in 38s
2026-06-12 13:21:22 +02:00
c702152cca Refactor real-mode memory allocation and identity mapping for AP trampoline
All checks were successful
Builds / ExectOS (amd64, release) (push) Successful in 36s
Builds / ExectOS (amd64, debug) (push) Successful in 34s
Builds / ExectOS (i686, debug) (push) Successful in 33s
Builds / ExectOS (i686, release) (push) Successful in 37s
2026-06-12 13:16:48 +02:00
81c799e590 Fix TrampolineCodeSize variable type
All checks were successful
Builds / ExectOS (amd64, debug) (push) Successful in 26s
Builds / ExectOS (i686, debug) (push) Successful in 32s
Builds / ExectOS (i686, release) (push) Successful in 37s
Builds / ExectOS (amd64, release) (push) Successful in 39s
2026-06-12 12:59:16 +02:00
cf0d7f0a40 Update trampoline size output parameter to PULONG across bootloader and kernel
Some checks failed
Builds / ExectOS (amd64, release) (push) Failing after 22s
Builds / ExectOS (amd64, debug) (push) Failing after 36s
Builds / ExectOS (i686, release) (push) Successful in 27s
Builds / ExectOS (i686, debug) (push) Successful in 36s
2026-06-12 12:54:53 +02:00
b0d2868f82 Update PTE mapping to allocate from PFN database
All checks were successful
Builds / ExectOS (amd64, debug) (push) Successful in 34s
Builds / ExectOS (i686, debug) (push) Successful in 33s
Builds / ExectOS (amd64, release) (push) Successful in 51s
Builds / ExectOS (i686, release) (push) Successful in 48s
2026-06-12 08:54:51 +02:00
32f0b747a1 Convert dispatcher context switch functions to naked assembly
All checks were successful
Builds / ExectOS (amd64, debug) (push) Successful in 38s
Builds / ExectOS (amd64, release) (push) Successful in 36s
Builds / ExectOS (i686, debug) (push) Successful in 37s
Builds / ExectOS (i686, release) (push) Successful in 34s
2026-06-10 16:48:54 +02:00
c57aa98923 Free affinity maps on allocation failure and remove redundant idle process affinity loop
All checks were successful
Builds / ExectOS (i686, debug) (push) Successful in 30s
Builds / ExectOS (amd64, release) (push) Successful in 41s
Builds / ExectOS (amd64, debug) (push) Successful in 42s
Builds / ExectOS (i686, release) (push) Successful in 34s
2026-06-10 14:08:07 +02:00
429e4ef6f1 Add bounds checking to affinity map bit operations and introduce InitializeAffinityMap
All checks were successful
Builds / ExectOS (amd64, release) (push) Successful in 34s
Builds / ExectOS (amd64, debug) (push) Successful in 40s
Builds / ExectOS (i686, debug) (push) Successful in 39s
Builds / ExectOS (i686, release) (push) Successful in 33s
2026-06-10 12:51:05 +02:00
39928f2ef4 Add documentation for InitializeProcessorAffinity
All checks were successful
Builds / ExectOS (i686, debug) (push) Successful in 34s
Builds / ExectOS (i686, release) (push) Successful in 34s
Builds / ExectOS (amd64, release) (push) Successful in 39s
Builds / ExectOS (amd64, debug) (push) Successful in 41s
2026-06-10 12:11:03 +02:00
51ec7e3bab Fix build by initializing thread dispatcher header
All checks were successful
Builds / ExectOS (amd64, release) (push) Successful in 31s
Builds / ExectOS (amd64, debug) (push) Successful in 31s
Builds / ExectOS (i686, debug) (push) Successful in 30s
Builds / ExectOS (i686, release) (push) Successful in 35s
2026-06-10 11:56:49 +02:00
f3ae70573c Initialize dispatcher header
Some checks failed
Builds / ExectOS (amd64, debug) (push) Successful in 36s
Builds / ExectOS (amd64, release) (push) Successful in 35s
Builds / ExectOS (i686, release) (push) Failing after 31s
Builds / ExectOS (i686, debug) (push) Failing after 33s
2026-06-10 11:46:26 +02:00
830f84ab26 Pass initial affinity map to InitializeProcess
All checks were successful
Builds / ExectOS (amd64, debug) (push) Successful in 38s
Builds / ExectOS (amd64, release) (push) Successful in 34s
Builds / ExectOS (i686, debug) (push) Successful in 33s
Builds / ExectOS (i686, release) (push) Successful in 36s
2026-06-10 11:27:25 +02:00
5a9df7ca86 Add helper to set full system processor affinity mask
All checks were successful
Builds / ExectOS (i686, release) (push) Successful in 37s
Builds / ExectOS (amd64, release) (push) Successful in 41s
Builds / ExectOS (i686, debug) (push) Successful in 8m22s
Builds / ExectOS (amd64, debug) (push) Successful in 8m24s
2026-06-10 11:13:28 +02:00
4bcdcda3a0 Change ActiveProcessors to a pointer for dynamic allocation
All checks were successful
Builds / ExectOS (i686, release) (push) Successful in 31s
Builds / ExectOS (amd64, debug) (push) Successful in 25s
Builds / ExectOS (i686, debug) (push) Successful in 40s
Builds / ExectOS (amd64, release) (push) Successful in 41s
2026-06-10 10:31:24 +02:00
7a27912dac Dynamically allocate active processors affinity map
Some checks failed
Builds / ExectOS (i686, release) (push) Failing after 27s
Builds / ExectOS (amd64, release) (push) Failing after 31s
Builds / ExectOS (i686, debug) (push) Failing after 56s
Builds / ExectOS (amd64, debug) (push) Failing after 59s
2026-06-10 10:22:15 +02:00
cf4b91ac83 Simplify active processor bit setting
All checks were successful
Builds / ExectOS (amd64, release) (push) Successful in 27s
Builds / ExectOS (amd64, debug) (push) Successful in 38s
Builds / ExectOS (i686, release) (push) Successful in 27s
Builds / ExectOS (i686, debug) (push) Successful in 38s
2026-06-09 23:27:24 +02:00
36c3d92399 Refactor idle thread initialization
All checks were successful
Builds / ExectOS (amd64, debug) (push) Successful in 35s
Builds / ExectOS (i686, release) (push) Successful in 39s
Builds / ExectOS (amd64, release) (push) Successful in 41s
Builds / ExectOS (i686, debug) (push) Successful in 35s
2026-06-09 23:24:40 +02:00
6a2a35c008 Refactor idle process initialization
All checks were successful
Builds / ExectOS (amd64, debug) (push) Successful in 31s
Builds / ExectOS (i686, debug) (push) Successful in 30s
Builds / ExectOS (i686, release) (push) Successful in 38s
Builds / ExectOS (amd64, release) (push) Successful in 40s
2026-06-09 23:17:03 +02:00
a9202f5b57 Refactor CalculateAffinityMapSize and add CreateAffinityMap
All checks were successful
Builds / ExectOS (amd64, debug) (push) Successful in 28s
Builds / ExectOS (amd64, release) (push) Successful in 41s
Builds / ExectOS (i686, release) (push) Successful in 39s
Builds / ExectOS (i686, debug) (push) Successful in 32s
2026-06-09 22:53:37 +02:00
4cbefe3a22 Implement affinity map bit manipulation and memory sizing helpers
All checks were successful
Builds / ExectOS (amd64, release) (push) Successful in 33s
Builds / ExectOS (i686, debug) (push) Successful in 41s
Builds / ExectOS (amd64, debug) (push) Successful in 42s
Builds / ExectOS (i686, release) (push) Successful in 30s
2026-06-09 20:17:47 +02:00
3841ceaf5b Refactor processor affinity logic
All checks were successful
Builds / ExectOS (amd64, debug) (push) Successful in 32s
Builds / ExectOS (i686, debug) (push) Successful in 31s
Builds / ExectOS (i686, release) (push) Successful in 40s
Builds / ExectOS (amd64, release) (push) Successful in 43s
2026-06-09 19:33:20 +02:00
e2eb784eef Enter idle loop instead of halting system
All checks were successful
Builds / ExectOS (amd64, release) (push) Successful in 32s
Builds / ExectOS (amd64, debug) (push) Successful in 42s
Builds / ExectOS (i686, release) (push) Successful in 30s
Builds / ExectOS (i686, debug) (push) Successful in 41s
2026-06-09 09:39:17 +02:00
6078a5ba29 Implement idle thread loop
Some checks failed
Builds / ExectOS (i686, release) (push) Successful in 32s
Builds / ExectOS (amd64, release) (push) Failing after 13m27s
Builds / ExectOS (amd64, debug) (push) Failing after 38m41s
Builds / ExectOS (i686, debug) (push) Failing after 42m56s
2026-06-09 08:36:39 +02:00
663f5cd048 Drop obsolete IPI exception dispatch path
All checks were successful
Builds / ExectOS (amd64, debug) (push) Successful in 34s
Builds / ExectOS (i686, debug) (push) Successful in 32s
Builds / ExectOS (i686, release) (push) Successful in 47s
Builds / ExectOS (amd64, release) (push) Successful in 49s
2026-06-08 20:55:17 +02:00
5999906bf0 Switch CPU exception IDT entries to interrupt gates to mask interrupts on entry
All checks were successful
Builds / ExectOS (amd64, debug) (push) Successful in 34s
Builds / ExectOS (amd64, release) (push) Successful in 32s
Builds / ExectOS (i686, debug) (push) Successful in 51s
Builds / ExectOS (i686, release) (push) Successful in 49s
2026-06-08 20:46:51 +02:00
1e0c1490fb Remove redundant IDT gate initialization for vector 0xE1
All checks were successful
Builds / ExectOS (amd64, debug) (push) Successful in 31s
Builds / ExectOS (i686, debug) (push) Successful in 30s
Builds / ExectOS (amd64, release) (push) Successful in 49s
Builds / ExectOS (i686, release) (push) Successful in 47s
2026-06-08 20:41:02 +02:00
5b0eebdb43 Initialize system interrupt handlers
All checks were successful
Builds / ExectOS (amd64, debug) (push) Successful in 29s
Builds / ExectOS (i686, release) (push) Successful in 30s
Builds / ExectOS (amd64, release) (push) Successful in 50s
Builds / ExectOS (i686, debug) (push) Successful in 49s
2026-06-08 20:15:18 +02:00
9e64939de4 Add XTCLINK linkage to KeStartXtSystem
All checks were successful
Builds / ExectOS (amd64, release) (push) Successful in 28s
Builds / ExectOS (amd64, debug) (push) Successful in 49s
Builds / ExectOS (i686, debug) (push) Successful in 47s
Builds / ExectOS (i686, release) (push) Successful in 31s
2026-06-08 20:06:23 +02:00
b911670121 Freeze secondary processors during kernel panic
All checks were successful
Builds / ExectOS (i686, debug) (push) Successful in 50s
Builds / ExectOS (amd64, debug) (push) Successful in 51s
Builds / ExectOS (i686, release) (push) Successful in 34s
Builds / ExectOS (amd64, release) (push) Successful in 36s
2026-06-08 15:02:55 +02:00
d175a817a5 Add IPI service routines for APC, DPC, and freeze request handling
All checks were successful
Builds / ExectOS (i686, debug) (push) Successful in 31s
Builds / ExectOS (amd64, debug) (push) Successful in 32s
Builds / ExectOS (i686, release) (push) Successful in 43s
Builds / ExectOS (amd64, release) (push) Successful in 46s
2026-06-08 14:49:02 +02:00
b285bc7312 Implement multi-processor freeze and thaw execution for SMP crash state synchronization
Some checks failed
Builds / ExectOS (amd64, debug) (push) Failing after 22s
Builds / ExectOS (i686, release) (push) Failing after 24s
Builds / ExectOS (amd64, release) (push) Failing after 40s
Builds / ExectOS (i686, debug) (push) Failing after 38s
2026-06-08 14:38:17 +02:00
c8cd198c4e Fix Task Register restoration by clearing busy bit in TSS descriptor
All checks were successful
Builds / ExectOS (amd64, release) (push) Successful in 34s
Builds / ExectOS (i686, release) (push) Successful in 32s
Builds / ExectOS (amd64, debug) (push) Successful in 47s
Builds / ExectOS (i686, debug) (push) Successful in 45s
2026-06-08 13:40:20 +02:00
95d45f5a0a Do not restore Task Register during AMD64 processor control state restoration
All checks were successful
Builds / ExectOS (i686, release) (push) Successful in 35s
Builds / ExectOS (amd64, release) (push) Successful in 37s
Builds / ExectOS (amd64, debug) (push) Successful in 52s
Builds / ExectOS (i686, debug) (push) Successful in 50s
2026-06-08 13:05:24 +02:00
766e4d9603 Register BSP in processor block array during initialization
All checks were successful
Builds / ExectOS (amd64, release) (push) Successful in 37s
Builds / ExectOS (i686, release) (push) Successful in 33s
Builds / ExectOS (i686, debug) (push) Successful in 49s
Builds / ExectOS (amd64, debug) (push) Successful in 51s
2026-06-08 11:21:53 +02:00
a601fd0afa Mark BSP processor as started
All checks were successful
Builds / ExectOS (amd64, debug) (push) Successful in 34s
Builds / ExectOS (amd64, release) (push) Successful in 32s
Builds / ExectOS (i686, release) (push) Successful in 51s
Builds / ExectOS (i686, debug) (push) Successful in 52s
2026-06-08 10:22:41 +02:00
cc23e459e0 Move SwitchProcessor to architecture-specific implementations
All checks were successful
Builds / ExectOS (amd64, debug) (push) Successful in 33s
Builds / ExectOS (i686, debug) (push) Successful in 31s
Builds / ExectOS (amd64, release) (push) Successful in 47s
Builds / ExectOS (i686, release) (push) Successful in 45s
2026-06-07 22:53:00 +02:00
d36b678ba1 Add kd/debug.cc to xtoskrnl source list
Some checks failed
Builds / ExectOS (amd64, debug) (push) Successful in 26s
Builds / ExectOS (i686, release) (push) Failing after 25s
Builds / ExectOS (amd64, release) (push) Successful in 43s
Builds / ExectOS (i686, debug) (push) Failing after 41s
2026-06-07 22:41:31 +02:00
43265bcddb Bypass debug I/O locks during kernel panic or debugger session
Some checks failed
Builds / ExectOS (amd64, release) (push) Failing after 29s
Builds / ExectOS (i686, release) (push) Failing after 26s
Builds / ExectOS (amd64, debug) (push) Failing after 41s
Builds / ExectOS (i686, debug) (push) Failing after 39s
2026-06-07 22:37:59 +02:00
47d4069d6f Add functions to save and restore processor context and control state
All checks were successful
Builds / ExectOS (amd64, release) (push) Successful in 31s
Builds / ExectOS (amd64, debug) (push) Successful in 33s
Builds / ExectOS (i686, debug) (push) Successful in 48s
Builds / ExectOS (i686, release) (push) Successful in 46s
2026-06-07 20:33:02 +02:00
904df63198 Remove duplicate context flag definitions
All checks were successful
Builds / ExectOS (i686, release) (push) Successful in 27s
Builds / ExectOS (amd64, debug) (push) Successful in 28s
Builds / ExectOS (amd64, release) (push) Successful in 47s
Builds / ExectOS (i686, debug) (push) Successful in 45s
2026-06-07 19:40:29 +02:00
1df971a71e Extend CONTEXT and PRCB structures with context flags and IPI state fields
All checks were successful
Builds / ExectOS (amd64, debug) (push) Successful in 33s
Builds / ExectOS (amd64, release) (push) Successful in 49s
Builds / ExectOS (i686, debug) (push) Successful in 47s
Builds / ExectOS (i686, release) (push) Successful in 31s
2026-06-07 18:47:48 +02:00
2a413d5717 Update processor state save calls
All checks were successful
Builds / ExectOS (i686, debug) (push) Successful in 33s
Builds / ExectOS (amd64, debug) (push) Successful in 50s
Builds / ExectOS (amd64, release) (push) Successful in 47s
Builds / ExectOS (i686, release) (push) Successful in 31s
2026-06-07 13:11:04 +02:00
9c2357dfe6 Expose installed CPU count and rename state save function
Some checks failed
Builds / ExectOS (amd64, debug) (push) Failing after 24s
Builds / ExectOS (i686, debug) (push) Failing after 24s
Builds / ExectOS (amd64, release) (push) Failing after 39s
Builds / ExectOS (i686, release) (push) Failing after 36s
2026-06-07 13:05:31 +02:00
f82562f450 Rename SwitchCpu to SwitchProcessor
All checks were successful
Builds / ExectOS (amd64, release) (push) Successful in 35s
Builds / ExectOS (amd64, debug) (push) Successful in 50s
Builds / ExectOS (i686, release) (push) Successful in 34s
Builds / ExectOS (i686, debug) (push) Successful in 48s
2026-06-07 12:33:56 +02:00
a33b63842a Add IPI definitions and frozen states, change KAFFINITY_MAP to flexible array
All checks were successful
Builds / ExectOS (amd64, debug) (push) Successful in 32s
Builds / ExectOS (i686, release) (push) Successful in 30s
Builds / ExectOS (amd64, release) (push) Successful in 47s
Builds / ExectOS (i686, debug) (push) Successful in 46s
2026-06-07 12:13:55 +02:00
4256a312ae Implement kernel debugger entry point
Some checks failed
Builds / ExectOS (amd64, debug) (push) Failing after 29s
Builds / ExectOS (i686, debug) (push) Failing after 27s
Builds / ExectOS (amd64, release) (push) Failing after 44s
Builds / ExectOS (i686, release) (push) Failing after 41s
2026-06-07 02:04:27 +02:00
678a0f4f48 Add static member definitions for kernel debugger active flag and kernel panic state
All checks were successful
Builds / ExectOS (i686, debug) (push) Successful in 32s
Builds / ExectOS (amd64, debug) (push) Successful in 34s
Builds / ExectOS (i686, release) (push) Successful in 45s
Builds / ExectOS (amd64, release) (push) Successful in 47s
2026-06-06 19:00:49 +02:00
7344c5ed4a Add function to query kernel debugger active state
Some checks failed
Builds / ExectOS (amd64, release) (push) Failing after 23s
Builds / ExectOS (amd64, debug) (push) Failing after 41s
Builds / ExectOS (i686, release) (push) Failing after 25s
Builds / ExectOS (i686, debug) (push) Failing after 39s
2026-06-06 18:57:32 +02:00
537fbc8af4 Track kernel panic state
Some checks failed
Builds / ExectOS (i686, release) (push) Failing after 31s
Builds / ExectOS (amd64, debug) (push) Failing after 41s
Builds / ExectOS (i686, debug) (push) Failing after 33s
Builds / ExectOS (amd64, release) (push) Failing after 39s
2026-06-06 18:52:05 +02:00
cf25af23d1 Add conditional acquisition parameter to RAII guard classes
All checks were successful
Builds / ExectOS (i686, debug) (push) Successful in 31s
Builds / ExectOS (amd64, debug) (push) Successful in 34s
Builds / ExectOS (amd64, release) (push) Successful in 58s
Builds / ExectOS (i686, release) (push) Successful in 55s
2026-06-06 17:26:39 +02:00
f680830b53 Implement resource cleanup for failed allocations during idle thread setup
All checks were successful
Builds / ExectOS (i686, debug) (push) Successful in 45s
Builds / ExectOS (amd64, release) (push) Successful in 47s
Builds / ExectOS (amd64, debug) (push) Successful in 47s
Builds / ExectOS (i686, release) (push) Successful in 45s
2026-06-04 14:36:43 +02:00
53a239958f Propagate allocation failures from idle process and thread setup
All checks were successful
Builds / ExectOS (amd64, release) (push) Successful in 33s
Builds / ExectOS (i686, debug) (push) Successful in 31s
Builds / ExectOS (i686, release) (push) Successful in 44s
Builds / ExectOS (amd64, debug) (push) Successful in 48s
2026-06-04 14:30:01 +02:00
f13326ffaf Add PS subsystem overview to kernel documentation
All checks were successful
Builds / ExectOS (i686, debug) (push) Successful in 32s
Builds / ExectOS (amd64, debug) (push) Successful in 32s
Builds / ExectOS (amd64, release) (push) Successful in 50s
Builds / ExectOS (i686, release) (push) Successful in 48s
2026-06-04 13:18:33 +02:00
75e7760d04 Delegate idle process and thread setup to PS subsystem
All checks were successful
Builds / ExectOS (amd64, debug) (push) Successful in 35s
Builds / ExectOS (i686, debug) (push) Successful in 33s
Builds / ExectOS (i686, release) (push) Successful in 44s
Builds / ExectOS (amd64, release) (push) Successful in 46s
2026-06-04 13:14:21 +02:00
02d0f3f538 Introduce PS subsystem with IDLE process and thread creation
All checks were successful
Builds / ExectOS (amd64, release) (push) Successful in 33s
Builds / ExectOS (i686, release) (push) Successful in 29s
Builds / ExectOS (amd64, debug) (push) Successful in 50s
Builds / ExectOS (i686, debug) (push) Successful in 48s
2026-06-04 13:09:09 +02:00
e2a78389f2 Fix incorrect namespace comment
All checks were successful
Builds / ExectOS (amd64, release) (push) Successful in 46s
Builds / ExectOS (amd64, debug) (push) Successful in 44s
Builds / ExectOS (i686, debug) (push) Successful in 41s
Builds / ExectOS (i686, release) (push) Successful in 42s
2026-06-04 12:58:59 +02:00
81fdf1f77a Allocate executive thread structure for idle thread and assign PRCB pointers
All checks were successful
Builds / ExectOS (amd64, release) (push) Successful in 31s
Builds / ExectOS (i686, debug) (push) Successful in 47s
Builds / ExectOS (amd64, debug) (push) Successful in 49s
Builds / ExectOS (i686, release) (push) Successful in 49s
2026-06-04 11:57:58 +02:00
631f58bf72 Update InitializeProcess doxygen 2026-06-04 11:57:56 +02:00
1d2d66fc83 Dedicated Idle process and thread initialization with dynamic affinity allocation 2026-06-04 11:57:49 +02:00
34aba8c7c7 Remove software interrupt 0x2F trap handler
All checks were successful
Builds / ExectOS (amd64, debug) (push) Successful in 45s
Builds / ExectOS (amd64, release) (push) Successful in 43s
Builds / ExectOS (i686, release) (push) Successful in 41s
Builds / ExectOS (i686, debug) (push) Successful in 43s
2026-06-03 15:57:12 +02:00
5e764a0d17 Fix IDT entry for vector 0x2F to use interrupt entry point
All checks were successful
Builds / ExectOS (amd64, debug) (push) Successful in 1m13s
Builds / ExectOS (amd64, release) (push) Successful in 1m11s
Builds / ExectOS (i686, debug) (push) Successful in 45s
Builds / ExectOS (i686, release) (push) Successful in 42s
2026-06-03 15:43:11 +02:00
65e86db731 Migrate thread affinity from GROUP_AFFINITY to KAFFINITY_MAP
All checks were successful
Builds / ExectOS (amd64, release) (push) Successful in 42s
Builds / ExectOS (amd64, debug) (push) Successful in 45s
Builds / ExectOS (i686, debug) (push) Successful in 43s
Builds / ExectOS (i686, release) (push) Successful in 41s
2026-06-01 22:28:21 +02:00
615d253bb4 Update initial thread and process affinity assignment to use group-aware structures
All checks were successful
Builds / ExectOS (amd64, debug) (push) Successful in 45s
Builds / ExectOS (amd64, release) (push) Successful in 43s
Builds / ExectOS (i686, debug) (push) Successful in 44s
Builds / ExectOS (i686, release) (push) Successful in 40s
2026-06-01 20:40:34 +02:00
2fcbc7bee8 Implement processor affinity search functions
Some checks failed
Builds / ExectOS (amd64, debug) (push) Failing after 33s
Builds / ExectOS (amd64, release) (push) Failing after 32s
Builds / ExectOS (i686, release) (push) Failing after 32s
Builds / ExectOS (i686, debug) (push) Failing after 34s
2026-06-01 01:10:40 +02:00
2c14da997d Convert process affinity assignment to KAFFINITY_MAP
Some checks failed
Builds / ExectOS (amd64, debug) (push) Failing after 34s
Builds / ExectOS (amd64, release) (push) Failing after 32s
Builds / ExectOS (i686, debug) (push) Failing after 34s
Builds / ExectOS (i686, release) (push) Failing after 32s
2026-06-01 01:06:13 +02:00
a7c2182d4a Extend processor affinity structures to support group affinity
Some checks failed
Builds / ExectOS (amd64, debug) (push) Failing after 33s
Builds / ExectOS (amd64, release) (push) Failing after 31s
Builds / ExectOS (i686, debug) (push) Failing after 31s
Builds / ExectOS (i686, release) (push) Failing after 30s
2026-06-01 01:03:18 +02:00
0aabc206a1 Add BSF and BSR instruction wrappers
All checks were successful
Builds / ExectOS (amd64, debug) (push) Successful in 55s
Builds / ExectOS (amd64, release) (push) Successful in 52s
Builds / ExectOS (i686, debug) (push) Successful in 42s
Builds / ExectOS (i686, release) (push) Successful in 40s
2026-06-01 00:36:52 +02:00
7d8b33390a Add runtime accounting and DPC throttling
All checks were successful
Builds / ExectOS (amd64, release) (push) Successful in 34s
Builds / ExectOS (i686, release) (push) Successful in 32s
Builds / ExectOS (amd64, debug) (push) Successful in 1m2s
Builds / ExectOS (i686, debug) (push) Successful in 1m0s
2026-05-30 23:53:47 +02:00
5a5604c35d Register dispatch interrupt handler
All checks were successful
Builds / ExectOS (i686, debug) (push) Successful in 31s
Builds / ExectOS (amd64, debug) (push) Successful in 32s
Builds / ExectOS (i686, release) (push) Successful in 52s
Builds / ExectOS (amd64, release) (push) Successful in 54s
2026-05-28 23:50:02 +02:00
addf9addab Verify system timer expiration on every clock interrupt
All checks were successful
Builds / ExectOS (amd64, release) (push) Successful in 36s
Builds / ExectOS (i686, debug) (push) Successful in 42s
Builds / ExectOS (amd64, debug) (push) Successful in 45s
Builds / ExectOS (i686, release) (push) Successful in 35s
2026-05-28 00:38:49 +02:00
f562aa0874 Implement timer table list and check for expired timers
All checks were successful
Builds / ExectOS (amd64, release) (push) Successful in 38s
Builds / ExectOS (i686, release) (push) Successful in 36s
Builds / ExectOS (amd64, debug) (push) Successful in 47s
Builds / ExectOS (i686, debug) (push) Successful in 46s
2026-05-28 00:36:25 +02:00
19a9dfe7c6 Add PrcbLock and runtime counters to KPROCESSOR_CONTROL_BLOCK
All checks were successful
Builds / ExectOS (i686, release) (push) Successful in 35s
Builds / ExectOS (amd64, release) (push) Successful in 37s
Builds / ExectOS (amd64, debug) (push) Successful in 45s
Builds / ExectOS (i686, debug) (push) Successful in 43s
2026-05-27 23:15:19 +02:00
46594f1fc3 Introduce KWAIT_REASON enumeration for thread wait reasons
All checks were successful
Builds / ExectOS (amd64, debug) (push) Successful in 26s
Builds / ExectOS (i686, debug) (push) Successful in 29s
Builds / ExectOS (amd64, release) (push) Successful in 36s
Builds / ExectOS (i686, release) (push) Successful in 38s
2026-05-27 20:23:18 +02:00
77 changed files with 3480 additions and 301 deletions

View File

@@ -30,7 +30,7 @@ namespace AR
public:
STATIC XTAPI VOID GetTrampolineInformation(IN TRAMPOLINE_TYPE TrampolineType,
OUT PVOID *TrampolineCode,
OUT PULONG_PTR TrampolineSize);
OUT PULONG TrampolineSize);
};
}

View File

@@ -116,7 +116,7 @@ Xtos::EnablePaging(IN PXTBL_PAGE_MAPPING PageMap)
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS TrampolineAddress;
PXT_TRAMPOLINE_ENTRY TrampolineEntry;
ULONG_PTR TrampolineSize;
ULONG TrampolineSize;
PVOID TrampolineCode;
/* Check the configured page map level to set the LA57 state accordingly */

View File

@@ -39,6 +39,9 @@
#define APIC_VECTOR_PERF 0xFE
#define APIC_VECTOR_NMI 0xFF
/* APIC SIPI vector shift */
#define APIC_VECTOR_SIPI_SHIFT 12
/* APIC destination formats */
#define APIC_DF_FLAT 0xFFFFFFFF
#define APIC_DF_CLUSTER 0x0FFFFFFF

View File

@@ -132,6 +132,18 @@
#define CONTEXT_SEGMENTS (CONTEXT_ARCHITECTURE | 0x04)
#define CONTEXT_FLOATING_POINT (CONTEXT_ARCHITECTURE | 0x08)
#define CONTEXT_DEBUG_REGISTERS (CONTEXT_ARCHITECTURE | 0x10)
#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT)
#define CONTEXT_ALL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | \
CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS)
/* Clock control flags */
#define CLOCK_QUANTUM_DECREMENT 3
/* DPC definitions */
#define DPC_ADJUST_THRESHOLD 20
#define DPC_IDEAL_RATE 20
#define DPC_MAXIMUM_QUEUE_DEPTH 4
#define DPC_MINIMUM_RATE 3
/* Interrupt request levels definitions */
#define PASSIVE_LEVEL 0
@@ -232,7 +244,7 @@ typedef struct _CONTEXT
USHORT SegFs;
USHORT SegGs;
USHORT SegSs;
ULONG EFlags;
ULONG Flags;
ULONG64 Dr0;
ULONG64 Dr1;
ULONG64 Dr2;
@@ -560,13 +572,27 @@ typedef struct _KPROCESSOR_CONTROL_BLOCK
ULONG_PTR SetMember;
CPU_IDENTIFICATION CpuId;
KPROCESSOR_STATE ProcessorState;
KSPIN_LOCK PrcbLock;
KSPIN_LOCK_QUEUE LockQueue[MaximumLock];
VOLATILE ULONG IpiFrozen;
VOLATILE LONG_PTR RequestSummary;
KDPC_DATA DpcData[2];
PVOID DpcStack;
LONG MaximumDpcQueueDepth;
ULONG DpcRequestRate;
BOOLEAN DpcInterruptRequested;
VOLATILE BOOLEAN DpcRoutineActive;
ULONG DpcLastCount;
VOLATILE ULONG_PTR TimerHand;
VOLATILE ULONG_PTR TimerRequest;
ULONG_PTR MultiThreadProcessorSet;
SINGLE_LIST_ENTRY DeferredReadyListHead;
ULONG InterruptCount;
ULONG KernelTime;
ULONG UserTime;
ULONG DpcTime;
ULONG InterruptTime;
ULONG AdjustDpcThreshold;
PROCESSOR_POWER_STATE PowerState;
ULONG ProfilingCountdown;
} KPROCESSOR_CONTROL_BLOCK, *PKPROCESSOR_CONTROL_BLOCK;

View File

@@ -57,7 +57,7 @@ typedef EFI_STATUS (XTCDECL *PBL_ALLOCATE_PAGES)(IN EFI_ALLOCATE_TYPE Allocation
typedef EFI_STATUS (XTCDECL *PBL_ALLOCATE_POOL)(IN UINT_PTR Size, OUT PVOID *Memory);
typedef EFI_STATUS (XTCDECL *PBL_BOOTMENU_INITIALIZE_OS_LIST)(IN ULONG MaxNameLength, OUT PXTBL_BOOTMENU_ITEM *MenuEntries, OUT PULONG EntriesCount, OUT PULONG DefaultId);
typedef BOOLEAN (XTCDECL *PBL_BOOTUTILS_GET_BOOLEAN_PARAMETER)(IN PCWSTR Parameters, IN PCWSTR Needle);
typedef VOID (XTAPI *PBL_BOOTUTILS_GET_TRAMPOLINE_INFORMATION)(IN TRAMPOLINE_TYPE TrampolineType, OUT PVOID *TrampolineCode, OUT PULONG_PTR TrampolineSize);
typedef VOID (XTAPI *PBL_BOOTUTILS_GET_TRAMPOLINE_INFORMATION)(IN TRAMPOLINE_TYPE TrampolineType, OUT PVOID *TrampolineCode, OUT PULONG TrampolineSize);
typedef EFI_STATUS (XTCDECL *PBL_BUILD_PAGE_MAP)(IN PXTBL_PAGE_MAPPING PageMap, IN ULONG_PTR SelfMapAddress);
typedef EFI_STATUS (XTCDECL *PBL_COMMIT_PAGE_MAP)(IN PXTBL_PAGE_MAPPING PageMap);
typedef EFI_STATUS (XTCDECL *PBL_CLOSE_VOLUME)(IN PEFI_HANDLE VolumeHandle);

View File

@@ -45,6 +45,9 @@
#define APIC_VECTOR_PERF 0xFE
#define APIC_VECTOR_NMI 0xFF
/* APIC SIPI vector shift */
#define APIC_VECTOR_SIPI_SHIFT 12
/* APIC destination formats */
#define APIC_DF_FLAT 0xFFFFFFFF
#define APIC_DF_CLUSTER 0x0FFFFFFF

View File

@@ -154,6 +154,19 @@
#define CONTEXT_FLOATING_POINT (CONTEXT_ARCHITECTURE | 0x08)
#define CONTEXT_DEBUG_REGISTERS (CONTEXT_ARCHITECTURE | 0x10)
#define CONTEXT_EXTENDED_REGISTERS (CONTEXT_ARCHITECTURE | 0x20)
#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS)
#define CONTEXT_ALL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | \
CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS | \
CONTEXT_EXTENDED_REGISTERS)
/* Clock control flags */
#define CLOCK_QUANTUM_DECREMENT 3
/* DPC definitions */
#define DPC_ADJUST_THRESHOLD 20
#define DPC_IDEAL_RATE 20
#define DPC_MAXIMUM_QUEUE_DEPTH 4
#define DPC_MINIMUM_RATE 3
/* Interrupt request levels definitions */
#define PASSIVE_LEVEL 0
@@ -291,7 +304,7 @@ typedef struct _CONTEXT
ULONG Ebp;
ULONG Eip;
ULONG SegCs;
ULONG EFlags;
ULONG Flags;
ULONG Esp;
ULONG SegSs;
UCHAR ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];
@@ -519,13 +532,27 @@ typedef struct _KPROCESSOR_CONTROL_BLOCK
ULONG_PTR SetMember;
CPU_IDENTIFICATION CpuId;
KPROCESSOR_STATE ProcessorState;
KSPIN_LOCK PrcbLock;
KSPIN_LOCK_QUEUE LockQueue[MaximumLock];
ULONG_PTR MultiThreadProcessorSet;
VOLATILE ULONG IpiFrozen;
VOLATILE LONG_PTR RequestSummary;
KDPC_DATA DpcData[2];
PVOID DpcStack;
LONG MaximumDpcQueueDepth;
ULONG DpcRequestRate;
BOOLEAN DpcInterruptRequested;
VOLATILE BOOLEAN DpcRoutineActive;
ULONG DpcLastCount;
VOLATILE ULONG_PTR TimerHand;
VOLATILE ULONG_PTR TimerRequest;
SINGLE_LIST_ENTRY DeferredReadyListHead;
ULONG InterruptCount;
ULONG KernelTime;
ULONG UserTime;
ULONG DpcTime;
ULONG InterruptTime;
ULONG AdjustDpcThreshold;
PROCESSOR_POWER_STATE PowerState;
ULONG ProfilingCountdown;
} KPROCESSOR_CONTROL_BLOCK, *PKPROCESSOR_CONTROL_BLOCK;

View File

@@ -24,14 +24,30 @@
/* Maximum number of exception parameters */
#define EXCEPTION_MAXIMUM_PARAMETERS 15
/* IPI types */
#define IPI_APC 1
#define IPI_DPC 2
#define IPI_FREEZE 4
#define IPI_PACKET_READY 8
#define IPI_SYNC_REQUEST 16
/* IPI frozen states */
#define IPI_FROZEN_STATE_RUNNING 0x00
#define IPI_FROZEN_STATE_FROZEN 0x02
#define IPI_FROZEN_STATE_THAW 0x03
#define IPI_FROZEN_STATE_OWNER 0x04
#define IPI_FROZEN_STATE_FREEZE 0x05
#define IPI_FROZEN_STATE_ACTIVE 0x20
/* APC pending state length */
#define KAPC_STATE_LENGTH (FIELD_OFFSET(KAPC_STATE, UserApcPending) + sizeof(BOOLEAN))
/* Kernel service descriptor tables count */
#define KSERVICE_TABLES_COUNT 4
/* Timer length */
/* Timer related definitions */
#define KTIMER_LENGTH (FIELD_OFFSET(KTIMER, Period) + sizeof(LONG))
#define KTIMER_TABLE_SIZE 512
/* Kernel builtin wait blocks */
#define EVENT_WAIT_BLOCK 2
@@ -79,6 +95,15 @@ typedef enum _KAPC_ENVIRONMENT
InsertApcEnvironment
} KAPC_ENVIRONMENT, *PKAPC_ENVIRONMENT;
/* Continue status enumeration list */
typedef enum _KCONTINUE_STATUS
{
ContinueError,
ContinueSuccess,
ContinueProcessorReselected,
ContinueNextProcessor
} KCONTINUE_STATUS, *PKCONTINUE_STATUS;
/* DPC importance enumeration list */
typedef enum _KDPC_IMPORTANCE
{
@@ -212,6 +237,55 @@ typedef enum _KTIMER_TYPE
SynchronizationTimer
} KTIMER_TYPE, *PKTIMER_TYPE;
/* Wait reason */
typedef enum _KWAIT_REASON
{
Executive,
FreePage,
PageIn,
PoolAllocation,
DelayExecution,
Suspended,
UserRequest,
WrExecutive,
WrFreePage,
WrPageIn,
WrPoolAllocation,
WrDelayExecution,
WrSuspended,
WrUserRequest,
WrEventPair,
WrQueue,
WrLpcReceive,
WrLpcReply,
WrVirtualMemory,
WrPageOut,
WrRendezvous,
WrKeyedEvent,
WrTerminated,
WrProcessInSwap,
WrCpuRateControl,
WrCalloutStack,
WrKernel,
WrResource,
WrPushLock,
WrMutex,
WrQuantumEnd,
WrDispatchInt,
WrPreempted,
WrYieldExecution,
WrFastMutex,
WrGuardedMutex,
WrRundown,
WrAlertByThreadId,
WrDeferredPreempt,
WrPhysicalFault,
WrIoRing,
WrMdlCache,
WrRcu,
MaximumWaitReason
} KWAIT_REASON, *PKWAIT_REASON;
/* APC Types */
typedef enum _MODE
{
@@ -263,6 +337,15 @@ typedef struct _EXCEPTION_RECORD
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
} EXCEPTION_RECORD, *PEXCEPTION_RECORD;
/* Extended affinity structure definition */
typedef struct _KAFFINITY_MAP
{
USHORT Count;
USHORT Size;
ULONG Reserved;
KAFFINITY Bitmap[];
} KAFFINITY_MAP, *PKAFFINITY_MAP;
/* Asynchronous Procedure Call (APC) object structure definition */
typedef struct _KAPC
{
@@ -419,7 +502,8 @@ typedef struct _KPROCESS
ULONG_PTR DirectoryTable[2];
USHORT IopmOffset;
UCHAR Iopl;
VOLATILE KAFFINITY ActiveProcessors;
PKAFFINITY_MAP Affinity;
PKAFFINITY_MAP ActiveProcessors;
ULONG KernelTime;
ULONG UserTime;
LIST_ENTRY ReadyListHead;
@@ -427,7 +511,6 @@ typedef struct _KPROCESS
PVOID VdmTrapHandler;
LIST_ENTRY ThreadListHead;
KSPIN_LOCK ProcessLock;
KAFFINITY Affinity;
union
{
struct
@@ -482,7 +565,6 @@ typedef struct _KTHREAD
PVOID StackBase;
PVOID StackLimit;
KSPIN_LOCK ThreadLock;
ULONG ContextSwitches;
VOLATILE UCHAR State;
UCHAR NpxState;
@@ -507,7 +589,7 @@ typedef struct _KTHREAD
PKWAIT_BLOCK WaitBlockList;
BOOLEAN Alertable;
BOOLEAN WaitNext;
UCHAR WaitReason;
KWAIT_REASON WaitReason;
SCHAR Priority;
UCHAR StackSwap;
VOLATILE UCHAR SwapBusy;
@@ -545,9 +627,9 @@ typedef struct _KTHREAD
CHAR PreviousMode;
UCHAR ResourceIndex;
UCHAR DisableBoost;
KAFFINITY UserAffinity;
PKAFFINITY_MAP UserAffinity;
PKPROCESS Process;
KAFFINITY Affinity;
PKAFFINITY_MAP Affinity;
PVOID ServiceTable;
PKAPC_STATE ApcStatePointer[2];
KAPC_STATE SavedApcState;
@@ -563,7 +645,7 @@ typedef struct _KTHREAD
LIST_ENTRY ThreadListEntry;
UCHAR LargeStack;
UCHAR PowerState;
UCHAR NpxIrql;
UCHAR NpxRunLevel;
UCHAR Spare5;
BOOLEAN AutoAlignment;
UCHAR Iopl;

View File

@@ -99,14 +99,20 @@ typedef struct _M128
/* Dispatcher object header structure definition */
typedef struct _DISPATCHER_HEADER
{
UCHAR Type;
union
{
struct
{
UCHAR Type;
UCHAR Absolute;
UCHAR NpxIrql;
};
UCHAR Size;
union {
UCHAR Inserted;
BOOLEAN DebugActive;
};
};
VOLATILE LONG Lock;
};
LONG SignalState;
LIST_ENTRY WaitListHead;
} DISPATCHER_HEADER, *PDISPATCHER_HEADER;

View File

@@ -48,6 +48,7 @@
/* XT status code definitions */
#define STATUS_SUCCESS ((XTSTATUS) 0x00000000L)
#define STATUS_WAKE_SYSTEM_DEBUGGER ((XTSTATUS) 0x80000007L)
#define STATUS_END_OF_MEDIA ((XTSTATUS) 0x8000001EL)
#define STATUS_RESOURCE_LOCKED ((XTSTATUS) 0xC0000000L)
#define STATUS_UNSUCCESSFUL ((XTSTATUS) 0xC0000001L)
@@ -59,6 +60,7 @@
#define STATUS_INVALID_PARAMETER ((XTSTATUS) 0xC000000DL)
#define STATUS_END_OF_FILE ((XTSTATUS) 0xC0000011L)
#define STATUS_NO_MEMORY ((XTSTATUS) 0xC0000017L)
#define STATUS_BUFFER_TOO_SMALL ((XTSTATUS) 0xC0000023L)
#define STATUS_PORT_DISCONNECTED ((XTSTATUS) 0xC0000037L)
#define STATUS_CRC_ERROR ((XTSTATUS) 0xC000003FL)
#define STATUS_FLOAT_OVERFLOW ((XTSTATUS) 0xC0000091L)

View File

@@ -43,6 +43,7 @@ typedef enum _EFI_UART_STOP_BITS_TYPE EFI_UART_STOP_BITS_TYPE, *PEFI_UART_STOP_B
typedef enum _EFI_UNIVERSA_GRAPHICS_BLT_OPERATION EFI_UNIVERSA_GRAPHICS_BLT_OPERATION, *PEFI_UNIVERSA_GRAPHICS_BLT_OPERATION;
typedef enum _HAL_APIC_MODE HAL_APIC_MODE, *PHAL_APIC_MODE;
typedef enum _KAPC_ENVIRONMENT KAPC_ENVIRONMENT, *PKAPC_ENVIRONMENT;
typedef enum _KCONTINUE_STATUS KCONTINUE_STATUS, *PKCONTINUE_STATUS;
typedef enum _KDPC_IMPORTANCE KDPC_IMPORTANCE, *PKDPC_IMPORTANCE;
typedef enum _KEVENT_TYPE KEVENT_TYPE, *PKEVENT_TYPE;
typedef enum _KOBJECTS KOBJECTS, *PKOBJECTS;
@@ -51,6 +52,7 @@ typedef enum _KPROFILE_SOURCE KPROFILE_SOURCE, *PKPROFILE_SOURCE;
typedef enum _KTHREAD_STATE KTHREAD_STATE, *PKTHREAD_STATE;
typedef enum _KTIMER_TYPE KTIMER_TYPE, *PKTIMER_TYPE;
typedef enum _KUBSAN_DATA_TYPE KUBSAN_DATA_TYPE, *PKUBSAN_DATA_TYPE;
typedef enum _KWAIT_REASON KWAIT_REASON, *PKWAIT_REASON;
typedef enum _LOADER_MEMORY_TYPE LOADER_MEMORY_TYPE, *PLOADER_MEMORY_TYPE;
typedef enum _MMPAGELISTS MMPAGELISTS, *PMMPAGELISTS;
typedef enum _MMPFN_CACHE_ATTRIBUTE MMPFN_CACHE_ATTRIBUTE, *PMMPFN_CACHE_ATTRIBUTE;
@@ -250,6 +252,7 @@ typedef struct _GENERIC_ADDRESS GENERIC_ADDRESS, *PGENERIC_ADDRESS;
typedef struct _GUID GUID, *PGUID;
typedef struct _HL_FRAMEBUFFER_DATA HL_FRAMEBUFFER_DATA, *PHL_FRAMEBUFFER_DATA;
typedef struct _HL_SCROLL_REGION_DATA HL_SCROLL_REGION_DATA, *PHL_SCROLL_REGION_DATA;
typedef struct _KAFFINITY_MAP KAFFINITY_MAP, *PKAFFINITY_MAP;
typedef struct _KAPC KAPC, *PKAPC;
typedef struct _KAPC_STATE KAPC_STATE, *PKAPC_STATE;
typedef struct _KD_DEBUG_MODE KD_DEBUG_MODE, *PKD_DEBUG_MODE;

View File

@@ -31,13 +31,16 @@ list(APPEND XTOSKRNL_SOURCE
${XTOSKRNL_SOURCE_DIR}/hl/fbdev.cc
${XTOSKRNL_SOURCE_DIR}/hl/init.cc
${XTOSKRNL_SOURCE_DIR}/hl/ioreg.cc
${XTOSKRNL_SOURCE_DIR}/kd/${ARCH}/debug.cc
${XTOSKRNL_SOURCE_DIR}/kd/data.cc
${XTOSKRNL_SOURCE_DIR}/kd/dbgio.cc
${XTOSKRNL_SOURCE_DIR}/kd/debug.cc
${XTOSKRNL_SOURCE_DIR}/kd/exports.cc
${XTOSKRNL_SOURCE_DIR}/ke/${ARCH}/dispatch.cc
${XTOSKRNL_SOURCE_DIR}/ke/${ARCH}/krnlinit.cc
${XTOSKRNL_SOURCE_DIR}/ke/${ARCH}/kthread.cc
${XTOSKRNL_SOURCE_DIR}/ke/${ARCH}/proc.cc
${XTOSKRNL_SOURCE_DIR}/ke/affinity.cc
${XTOSKRNL_SOURCE_DIR}/ke/apc.cc
${XTOSKRNL_SOURCE_DIR}/ke/bootinfo.cc
${XTOSKRNL_SOURCE_DIR}/ke/crash.cc
@@ -46,6 +49,7 @@ list(APPEND XTOSKRNL_SOURCE
${XTOSKRNL_SOURCE_DIR}/ke/dpc.cc
${XTOSKRNL_SOURCE_DIR}/ke/event.cc
${XTOSKRNL_SOURCE_DIR}/ke/exports.cc
${XTOSKRNL_SOURCE_DIR}/ke/ipi.cc
${XTOSKRNL_SOURCE_DIR}/ke/kprocess.cc
${XTOSKRNL_SOURCE_DIR}/ke/krnlinit.cc
${XTOSKRNL_SOURCE_DIR}/ke/kthread.cc
@@ -55,6 +59,7 @@ list(APPEND XTOSKRNL_SOURCE
${XTOSKRNL_SOURCE_DIR}/ke/shdata.cc
${XTOSKRNL_SOURCE_DIR}/ke/spinlock.cc
${XTOSKRNL_SOURCE_DIR}/ke/sysres.cc
${XTOSKRNL_SOURCE_DIR}/ke/sysserv.cc
${XTOSKRNL_SOURCE_DIR}/ke/systime.cc
${XTOSKRNL_SOURCE_DIR}/ke/timer.cc
${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/mmgr.cc
@@ -76,6 +81,8 @@ list(APPEND XTOSKRNL_SOURCE
${XTOSKRNL_SOURCE_DIR}/mm/pool.cc
${XTOSKRNL_SOURCE_DIR}/mm/pte.cc
${XTOSKRNL_SOURCE_DIR}/po/idle.cc
${XTOSKRNL_SOURCE_DIR}/ps/process.cc
${XTOSKRNL_SOURCE_DIR}/ps/thread.cc
${XTOSKRNL_SOURCE_DIR}/rtl/${ARCH}/dispatch.cc
${XTOSKRNL_SOURCE_DIR}/rtl/${ARCH}/exsup.cc
${XTOSKRNL_SOURCE_DIR}/rtl/${ARCH}/intrin.cc

View File

@@ -40,6 +40,7 @@ corresponding C++ namespace in which the subsystem's classes and routines reside
* Ke - Core Kernel Library
* Mm - Memory Manager
* Po - Plug&Play and Power Manager
* Ps - Process and Thread Manager
* Rtl - Runtime library
### AR: Architecture Library
@@ -76,6 +77,12 @@ This subsystem handles power management events, such as shutdown or standby. It
supporting device detection and installation at boot time. Furthermore, it is responsible for starting and stopping
devices on demand.
### PS: Process and Thread Manager
This subsystem is responsible for managing the lifecycle of processes and threads within the operating system. It
handles the creation, termination, and state tracking of these execution units. Furthermore, it provides the high-level
executive abstractions required to allocate system resources, manage process boundaries, and coordinate with the core
kernel for thread execution.
### RTL: Runtime Library
The Runtime Library provides a kernel-mode implementation of common C library functions. It includes many utility
routines, for use by other kernel components.

View File

@@ -617,6 +617,56 @@ AR::CpuFunctions::ReadWriteBarrier(VOID)
: "memory");
}
/**
* Performs a Bit Scan Forward instruction to locate the most significant set bit.
*
* @param Index
* Receives the zero-based index of the highest set bit when one is found.
*
* @param Mask
* Supplies the bitmap to scan.
*
* @return This routine returns TRUE when a set bit was found, otherwise FALSE.
*
* @since XT 1.0
*/
XTCDECL
BOOLEAN
AR::CpuFunctions::ScanForwardBit(OUT PULONG Index,
IN ULONG Mask)
{
/* Defer to the BSF instruction */
__asm__("bsfl %[Mask], %[Index]" : [Index] "=r" (*Index) : [Mask] "mr" (Mask));
/* Report whether the input had any bit set */
return Mask ? TRUE : FALSE;
}
/**
* Performs a Bit Scan Reverse instruction to locate the most significant set bit.
*
* @param Index
* Receives the zero-based index of the highest set bit when one is found.
*
* @param Mask
* Supplies the bitmap to scan.
*
* @return This routine returns TRUE when a set bit was found, otherwise FALSE.
*
* @since XT 1.0
*/
XTCDECL
BOOLEAN
AR::CpuFunctions::ScanReverseBit(OUT PULONG Index,
IN ULONG Mask)
{
/* Defer to the BSR instruction */
__asm__("bsrl %[Mask], %[Index]" : [Index] "=r" (*Index) : [Mask] "mr" (Mask));
/* Report whether the input had any bit set */
return Mask ? TRUE : FALSE;
}
/**
* Instructs the processor to set the interrupt flag.
*

View File

@@ -28,7 +28,7 @@ XTAPI
VOID
AR::ProcessorSupport::GetTrampolineInformation(IN TRAMPOLINE_TYPE TrampolineType,
OUT PVOID *TrampolineCode,
OUT PULONG_PTR TrampolineSize)
OUT PULONG TrampolineSize)
{
/* Get trampoline information */
switch(TrampolineType)
@@ -320,30 +320,28 @@ AR::ProcessorSupport::InitializeIdt(IN PKPROCESSOR_BLOCK ProcessorBlock)
}
/* Setup IDT handlers for known interrupts and traps */
SetIdtGate(ProcessorBlock->IdtBase, 0x00, (PVOID)ArTrapEntry[0x00], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x01, (PVOID)ArTrapEntry[0x01], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x00, (PVOID)ArTrapEntry[0x00], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x01, (PVOID)ArTrapEntry[0x01], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x02, (PVOID)ArTrapEntry[0x02], KGDT_R0_CODE, KIDT_IST_NMI, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x03, (PVOID)ArTrapEntry[0x03], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING3, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x04, (PVOID)ArTrapEntry[0x04], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING3, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x05, (PVOID)ArTrapEntry[0x05], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x06, (PVOID)ArTrapEntry[0x06], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x07, (PVOID)ArTrapEntry[0x07], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x08, (PVOID)ArTrapEntry[0x08], KGDT_R0_CODE, KIDT_IST_PANIC, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x09, (PVOID)ArTrapEntry[0x09], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x0A, (PVOID)ArTrapEntry[0x0A], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x0B, (PVOID)ArTrapEntry[0x0B], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x0C, (PVOID)ArTrapEntry[0x0C], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x0D, (PVOID)ArTrapEntry[0x0D], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x0E, (PVOID)ArTrapEntry[0x0E], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x10, (PVOID)ArTrapEntry[0x10], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x11, (PVOID)ArTrapEntry[0x11], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x12, (PVOID)ArTrapEntry[0x12], KGDT_R0_CODE, KIDT_IST_MCA, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x13, (PVOID)ArTrapEntry[0x13], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x03, (PVOID)ArTrapEntry[0x03], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING3, AMD64_INTERRUPT_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x04, (PVOID)ArTrapEntry[0x04], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING3, AMD64_INTERRUPT_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x05, (PVOID)ArTrapEntry[0x05], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x06, (PVOID)ArTrapEntry[0x06], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x07, (PVOID)ArTrapEntry[0x07], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x08, (PVOID)ArTrapEntry[0x08], KGDT_R0_CODE, KIDT_IST_PANIC, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x09, (PVOID)ArTrapEntry[0x09], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x0A, (PVOID)ArTrapEntry[0x0A], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x0B, (PVOID)ArTrapEntry[0x0B], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x0C, (PVOID)ArTrapEntry[0x0C], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x0D, (PVOID)ArTrapEntry[0x0D], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x0E, (PVOID)ArTrapEntry[0x0E], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x10, (PVOID)ArTrapEntry[0x10], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x11, (PVOID)ArTrapEntry[0x11], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x12, (PVOID)ArTrapEntry[0x12], KGDT_R0_CODE, KIDT_IST_MCA, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x13, (PVOID)ArTrapEntry[0x13], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x1F, (PVOID)ArTrapEntry[0x1F], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x2C, (PVOID)ArTrapEntry[0x2C], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING3, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x2D, (PVOID)ArTrapEntry[0x2D], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING3, AMD64_TRAP_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x2F, (PVOID)ArTrapEntry[0x2F], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0xE1, (PVOID)ArInterruptEntry[0xE1], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x2C, (PVOID)ArTrapEntry[0x2C], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING3, AMD64_INTERRUPT_GATE);
SetIdtGate(ProcessorBlock->IdtBase, 0x2D, (PVOID)ArTrapEntry[0x2D], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING3, AMD64_INTERRUPT_GATE);
}
/**
@@ -477,8 +475,9 @@ AR::ProcessorSupport::InitializeProcessorBlock(OUT PKPROCESSOR_BLOCK ProcessorBl
/* Set initial MXCSR register value */
ProcessorBlock->Prcb.MxCsr = INITIAL_MXCSR;
/* Set initial runlevel */
/* Set initial runlevel and mark processor as started */
ProcessorBlock->RunLevel = PASSIVE_LEVEL;
ProcessorBlock->Started = TRUE;
}
/**

View File

@@ -171,14 +171,6 @@ AR::Traps::DispatchTrap(IN PKTRAP_FRAME TrapFrame)
/* Debug-Service-Request raised */
HandleTrap2D(TrapFrame);
break;
case 0x2F:
/* Software Interrupt at DISPATCH level */
HandleTrap2F(TrapFrame);
break;
case 0xE1:
/* InterProcessor Interrupt (IPI) */
HandleTrapE1(TrapFrame);
break;
default:
/* Unknown/Unexpected trap */
HandleTrapFF(TrapFrame);
@@ -608,40 +600,6 @@ AR::Traps::HandleTrap2D(IN PKTRAP_FRAME TrapFrame)
KE::Crash::Panic(0x2D);
}
/**
* Handles the trap 0x2F when a software interrupt gets generated at DISPATCH_LEVEL.
*
* @param TrapFrame
* Supplies a kernel trap frame pushed by common trap handler on the stack.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTCDECL
VOID
AR::Traps::HandleTrap2F(IN PKTRAP_FRAME TrapFrame)
{
DebugPrint(L"Unhandled software interrupt at DISPATCH level (0x2F)!\n");
}
/**
* Handles the trap 0xE1 when InterProcessor Interrupt (IPI) occurs.
*
* @param TrapFrame
* Supplies a kernel trap frame pushed by common trap handler on the stack.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTCDECL
VOID
AR::Traps::HandleTrapE1(IN PKTRAP_FRAME TrapFrame)
{
DebugPrint(L"Unhandled IPI interrupt (0xE1)!\n");
}
/**
* Handles the trap 0xFF when Unexpected Interrupt occurs.
*

View File

@@ -587,6 +587,56 @@ AR::CpuFunctions::ReadWriteBarrier(VOID)
: "memory");
}
/**
* Performs a Bit Scan Forward instruction to locate the most significant set bit.
*
* @param Index
* Receives the zero-based index of the highest set bit when one is found.
*
* @param Mask
* Supplies the bitmap to scan.
*
* @return This routine returns TRUE when a set bit was found, otherwise FALSE.
*
* @since XT 1.0
*/
XTCDECL
BOOLEAN
AR::CpuFunctions::ScanForwardBit(OUT PULONG Index,
IN ULONG Mask)
{
/* Defer to the BSF instruction */
__asm__("bsfl %[Mask], %[Index]" : [Index] "=r" (*Index) : [Mask] "mr" (Mask));
/* Report whether the input had any bit set */
return Mask ? TRUE : FALSE;
}
/**
* Performs a Bit Scan Reverse instruction to locate the most significant set bit.
*
* @param Index
* Receives the zero-based index of the highest set bit when one is found.
*
* @param Mask
* Supplies the bitmap to scan.
*
* @return This routine returns TRUE when a set bit was found, otherwise FALSE.
*
* @since XT 1.0
*/
XTCDECL
BOOLEAN
AR::CpuFunctions::ScanReverseBit(OUT PULONG Index,
IN ULONG Mask)
{
/* Defer to the BSR instruction */
__asm__("bsrl %[Mask], %[Index]" : [Index] "=r" (*Index) : [Mask] "mr" (Mask));
/* Report whether the input had any bit set */
return Mask ? TRUE : FALSE;
}
/**
* Instructs the processor to set the interrupt flag.
*

View File

@@ -28,7 +28,7 @@ XTAPI
VOID
AR::ProcessorSupport::GetTrampolineInformation(IN TRAMPOLINE_TYPE TrampolineType,
OUT PVOID *TrampolineCode,
OUT PULONG_PTR TrampolineSize)
OUT PULONG TrampolineSize)
{
/* Get trampoline information */
switch(TrampolineType)
@@ -465,8 +465,9 @@ AR::ProcessorSupport::InitializeProcessorBlock(OUT PKPROCESSOR_BLOCK ProcessorBl
ProcessorBlock->Prcb.IdleThread = &(KE::KThread::GetInitialThread())->ThreadControlBlock;
ProcessorBlock->Prcb.NextThread = NULLPTR;
/* Set initial runlevel */
/* Set initial runlevel and mark processor as started */
ProcessorBlock->RunLevel = PASSIVE_LEVEL;
ProcessorBlock->Started = TRUE;
}
/**

View File

@@ -28,7 +28,7 @@ ACPI_SYSTEM_INFO HL::Acpi::SystemInfo;
ACPI_TIMER_INFO HL::Acpi::TimerInfo;
/* Represents the number of active processors */
KAFFINITY HL::Cpu::ActiveProcessors;
PKAFFINITY_MAP HL::Cpu::ActiveProcessors;
/* Metadata detailing the linear frame buffer geometry */
HL_FRAMEBUFFER_DATA HL::FrameBuffer::FrameBufferData;

View File

@@ -24,7 +24,6 @@ VOID
HL::Cpu::InitializeProcessor(VOID)
{
PKPROCESSOR_BLOCK ProcessorBlock;
KAFFINITY Affinity;
/* Get current processor block */
ProcessorBlock = KE::Processor::GetCurrentProcessorBlock();
@@ -33,17 +32,46 @@ HL::Cpu::InitializeProcessor(VOID)
ProcessorBlock->StallScaleFactor = INITIAL_STALL_FACTOR;
ProcessorBlock->Idr = 0xFFFFFFFF;
/* Set processor affinity */
Affinity = (KAFFINITY) 1 << ProcessorBlock->CpuNumber;
/* Apply affinity to a set of processors */
ActiveProcessors |= Affinity;
/* Check if active processors map is initialized */
if(ActiveProcessors != NULLPTR)
{
/* Register this CPU in the global active processors map */
KE::Affinity::AtomicSetProcessorAffinity(ActiveProcessors, ProcessorBlock->CpuNumber);
}
/* Initialize APIC for this processor */
HL::Pic::InitializePic();
/* Set the APIC running level */
HL::RunLevel::SetRunLevel(KE::Processor::GetCurrentProcessorBlock()->RunLevel);
HL::RunLevel::SetRunLevel(ProcessorBlock->RunLevel);
}
/**
* Initializes the global processor affinity map for active processors and registers Bootstrap Processor (BSP).
*
* @return This routine returns a status code indicating the success or failure of the operation.
*
* @since XT 1.0
*/
XTAPI
XTSTATUS
HL::Cpu::InitializeProcessorAffinity(VOID)
{
XTSTATUS Status;
/* Allocate an array of pointers */
Status = KE::Affinity::CreateAffinityMap(KE::Processor::GetInstalledCpus(), &ActiveProcessors);
if(Status != STATUS_SUCCESS)
{
/* Failed to allocate memory, return error */
return Status;
}
/* Register BSP in the global active processors map */
KE::Affinity::SetProcessorAffinity(ActiveProcessors, 0);
/* Return success */
return STATUS_SUCCESS;
}
/**
@@ -57,9 +85,9 @@ XTAPI
XTSTATUS
HL::Cpu::StartAllProcessors(VOID)
{
ULONG CpuNumber, Index, MaxCpus, SipiVector, Timeout, TrampolinePages;
PVOID CpuStructures, TrampolineAddress, TrampolineCode;
ULONG_PTR AllocationSize, TrampolineCodeSize;
ULONG ApPages, CpuNumber, Index, MaxCpus, SipiVector, Timeout, TrampolineCodeSize;
PVOID ApVirtualAddress, CpuStructures, TrampolineCode;
PHYSICAL_ADDRESS ApPhysicalAddress;
PPROCESSOR_START_BLOCK StartBlock;
PKPROCESSOR_BLOCK ProcessorBlock;
PACPI_SYSTEM_INFO SysInfo;
@@ -108,27 +136,34 @@ HL::Cpu::StartAllProcessors(VOID)
return STATUS_UNSUCCESSFUL;
}
/* Compute trampoline memory allocation size (trampoline + processor start block + temporary stack) */
AllocationSize = TrampolineCodeSize + sizeof(PROCESSOR_START_BLOCK) + 512;
TrampolinePages = (ULONG)(ROUND_UP(AllocationSize, MM_PAGE_SIZE) / MM_PAGE_SIZE);
/* Allocate real mode memory for AP trampoline */
Status = MM::HardwarePool::AllocateRealModeMemory(TrampolinePages, &TrampolineAddress);
/* Allocate low memory for AP trampoline code */
Status = MM::HardwarePool::AllocateLowMemory(&ApPhysicalAddress, &ApVirtualAddress);
if(Status != STATUS_SUCCESS)
{
/* Failed to allocate memory, print error message and return error */
DebugPrint(L"Failed to allocate %lu pages for AP Trampoline!\n", TrampolinePages);
DebugPrint(L"Failed to allocate low memory for AP Trampoline!\n");
return Status;
}
/* Copy trampoline code to low memory */
RTL::Memory::CopyMemory(TrampolineAddress, TrampolineCode, TrampolineCodeSize);
RTL::Memory::CopyMemory(ApVirtualAddress, TrampolineCode, TrampolineCodeSize);
/* Compute number of pages for trampoline */
ApPages = MM::HardwarePool::CalculateRealModeAllocationPages(TrampolineCodeSize);
/* Temporarily identity map trampoline address */
Status = MM::HardwarePool::MapRealModeMemory(ApPhysicalAddress, ApPages);
if(Status != STATUS_SUCCESS)
{
/* Failed to map memory, return error */
return Status;
}
/* Get start block address relative to trampoline address */
StartBlock = (PPROCESSOR_START_BLOCK)((PUCHAR)TrampolineAddress + TrampolineCodeSize);
StartBlock = (PPROCESSOR_START_BLOCK)((PUCHAR)ApVirtualAddress + TrampolineCodeSize);
/* Get SIPI vector */
SipiVector = (ULONG)((ULONG_PTR)TrampolineAddress >> 12);
SipiVector = (ULONG)(ApPhysicalAddress.QuadPart >> APIC_VECTOR_SIPI_SHIFT);
/* Loop over all CPUs */
CpuNumber = 0;
@@ -155,8 +190,8 @@ HL::Cpu::StartAllProcessors(VOID)
Status = MM::KernelPool::AllocateProcessorStructures(&CpuStructures);
if(Status != STATUS_SUCCESS)
{
/* Failed to allocate memory, unmap memory and return error */
MM::HardwarePool::UnmapHardwareMemory(TrampolineAddress, TrampolinePages, TRUE);
/* Failed to allocate memory, unmap temporary identity mapping and return error */
MM::HardwarePool::UnmapRealModeMemory(ApPhysicalAddress, ApPages);
return Status;
}
@@ -214,7 +249,7 @@ HL::Cpu::StartAllProcessors(VOID)
}
}
/* Unmap trampoline memory and return success */
MM::HardwarePool::UnmapHardwareMemory(TrampolineAddress, TrampolinePages, TRUE);
/* Unmap temporary identity mapping and return success */
MM::HardwarePool::UnmapRealModeMemory(ApPhysicalAddress, ApPages);
return STATUS_SUCCESS;
}

View File

@@ -42,6 +42,10 @@ namespace AR
STATIC XTCDECL ULONGLONG ReadTimeStampCounter(VOID);
STATIC XTCDECL ULONGLONG ReadTimeStampCounterProcessor(OUT PULONG TscAux);
STATIC XTCDECL VOID ReadWriteBarrier(VOID);
STATIC XTCDECL BOOLEAN ScanForwardBit(OUT PULONG Index,
IN ULONG Mask);
STATIC XTCDECL BOOLEAN ScanReverseBit(OUT PULONG Index,
IN ULONG Mask);
STATIC XTCDECL VOID SetInterruptFlag(VOID);
STATIC XTCDECL VOID StoreGlobalDescriptorTable(OUT PVOID Destination);
STATIC XTCDECL VOID StoreInterruptDescriptorTable(OUT PVOID Destination);

View File

@@ -30,7 +30,7 @@ namespace AR
STATIC XTAPI PVOID GetBootStack(VOID);
STATIC XTAPI VOID GetTrampolineInformation(IN TRAMPOLINE_TYPE TrampolineType,
OUT PVOID *TrampolineCode,
OUT PULONG_PTR TrampolineSize);
OUT PULONG TrampolineSize);
STATIC XTAPI VOID InitializeProcessor(IN PVOID ProcessorStructures);
STATIC XTAPI VOID InitializeProcessorStructures(IN PVOID ProcessorStructures,
OUT PKGDTENTRY *Gdt,

View File

@@ -51,8 +51,6 @@ namespace AR
STATIC XTCDECL VOID HandleTrap1F(IN PKTRAP_FRAME TrapFrame);
STATIC XTCDECL VOID HandleTrap2C(IN PKTRAP_FRAME TrapFrame);
STATIC XTCDECL VOID HandleTrap2D(IN PKTRAP_FRAME TrapFrame);
STATIC XTCDECL VOID HandleTrap2F(IN PKTRAP_FRAME TrapFrame);
STATIC XTCDECL VOID HandleTrapE1(IN PKTRAP_FRAME TrapFrame);
STATIC XTCDECL VOID HandleTrapFF(IN PKTRAP_FRAME TrapFrame);
};
}

View File

@@ -41,6 +41,10 @@ namespace AR
STATIC XTCDECL ULONGLONG ReadTimeStampCounter(VOID);
STATIC XTCDECL ULONGLONG ReadTimeStampCounterProcessor(OUT PULONG TscAux);
STATIC XTCDECL VOID ReadWriteBarrier(VOID);
STATIC XTCDECL BOOLEAN ScanForwardBit(OUT PULONG Index,
IN ULONG Mask);
STATIC XTCDECL BOOLEAN ScanReverseBit(OUT PULONG Index,
IN ULONG Mask);
STATIC XTCDECL VOID SetInterruptFlag(VOID);
STATIC XTCDECL VOID StoreGlobalDescriptorTable(OUT PVOID Destination);
STATIC XTCDECL VOID StoreInterruptDescriptorTable(OUT PVOID Destination);

View File

@@ -33,7 +33,7 @@ namespace AR
STATIC XTAPI PVOID GetBootStack(VOID);
STATIC XTAPI VOID GetTrampolineInformation(IN TRAMPOLINE_TYPE TrampolineType,
OUT PVOID *TrampolineCode,
OUT PULONG_PTR TrampolineSize);
OUT PULONG TrampolineSize);
STATIC XTAPI VOID InitializeProcessor(IN PVOID ProcessorStructures);
STATIC XTAPI VOID InitializeProcessorStructures(IN PVOID ProcessorStructures,
OUT PKGDTENTRY *Gdt,

View File

@@ -18,10 +18,11 @@ namespace HL
class Cpu
{
private:
STATIC KAFFINITY ActiveProcessors;
STATIC PKAFFINITY_MAP ActiveProcessors;
public:
STATIC XTAPI VOID InitializeProcessor(VOID);
STATIC XTAPI XTSTATUS InitializeProcessorAffinity(VOID);
STATIC XTAPI XTSTATUS StartAllProcessors(VOID);
};
}

View File

@@ -13,5 +13,6 @@
#include <kd/dbg.hh>
#include <kd/dbgio.hh>
#include <kd/debug.hh>
#endif /* __XTOSKRNL_KD_HH */

View File

@@ -0,0 +1,38 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/includes/kd/debug.hh
* DESCRIPTION: Kernel Debugger
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#ifndef __XTOSKRNL_KD_DEBUG_HH
#define __XTOSKRNL_KD_DEBUG_HH
#include <xtos.hh>
/* Kernel Debugger */
namespace KD
{
class Debugger
{
public:
STATIC PKD_PRINT_ROUTINE KdPrint;
private:
STATIC BOOLEAN Active;
public:
STATIC XTAPI BOOLEAN DebuggerActive(VOID);
STATIC XTAPI VOID EnterDebugger(IN PKTRAP_FRAME TrapFrame);
STATIC XTAPI KCONTINUE_STATUS SwitchProcessor(VOID);
private:
STATIC XTAPI BOOLEAN ProcessCpuStateChange(IN PEXCEPTION_RECORD ExceptionRecord,
IN OUT PCONTEXT Context,
IN BOOLEAN SecondChanceException);
};
}
#endif /* __XTOSKRNL_KD_DEBUG_HH */

View File

@@ -11,6 +11,7 @@
#include <xtos.hh>
#include <ke/affinity.hh>
#include <ke/apc.hh>
#include <ke/bootinfo.hh>
#include <ke/crash.hh>
@@ -18,6 +19,7 @@
#include <ke/dpc.hh>
#include <ke/event.hh>
#include <ke/guard.hh>
#include <ke/ipi.hh>
#include <ke/kprocess.hh>
#include <ke/krnlinit.hh>
#include <ke/kthread.hh>
@@ -28,6 +30,7 @@
#include <ke/shdata.hh>
#include <ke/spinlock.hh>
#include <ke/sysres.hh>
#include <ke/sysserv.hh>
#include <ke/systime.hh>
#include <ke/timer.hh>

View File

@@ -0,0 +1,49 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/includes/ke/affinity.hh
* DESCRIPTION: XT kernel processor affinity management support
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#ifndef __XTOSKRNL_KE_AFFINITY_HH
#define __XTOSKRNL_KE_AFFINITY_HH
#include <xtos.hh>
/* Kernel Library */
namespace KE
{
class Affinity
{
public:
STATIC XTFASTCALL VOID AtomicSetProcessorAffinity(IN OUT PKAFFINITY_MAP AffinityMap,
IN ULONG CpuNumber);
STATIC XTFASTCALL VOID CalculateAffinityMapSize(IN ULONG CpuCount,
OUT PULONG RequiredMapSize,
OUT PULONG RequiredBlockCount);
STATIC XTFASTCALL BOOLEAN CheckProcessorAffinity(IN PKAFFINITY_MAP AffinityMap,
IN ULONG CpuNumber);
STATIC XTFASTCALL VOID ClearAffinityMap(IN OUT PKAFFINITY_MAP AffinityMap);
STATIC XTFASTCALL VOID ClearProcessorAffinity(IN OUT PKAFFINITY_MAP AffinityMap,
IN ULONG CpuNumber);
STATIC XTAPI XTSTATUS CopyAffinity(OUT PKAFFINITY_MAP Destination,
IN PKAFFINITY_MAP Source);
STATIC XTAPI XTSTATUS CreateAffinityMap(IN ULONG CpuCount,
OUT PKAFFINITY_MAP* AffinityMap);
STATIC XTAPI VOID DestroyAffinityMap(IN PKAFFINITY_MAP AffinityMap);
STATIC XTAPI ULONG FindNextLeftSetProcessor(IN ULONG ThreadSeed,
IN PKAFFINITY_MAP AffinityMap);
STATIC XTAPI ULONG FindNextRightSetProcessor(IN ULONG ThreadSeed,
IN PKAFFINITY_MAP AffinityMap);
STATIC XTAPI XTSTATUS InitializeAffinityMap(IN OUT PKAFFINITY_MAP AffinityMap,
IN ULONG BufferSize);
STATIC XTFASTCALL VOID SetAllProcessorsAffinity(IN OUT PKAFFINITY_MAP AffinityMap);
STATIC XTFASTCALL VOID SetProcessorAffinity(IN OUT PKAFFINITY_MAP AffinityMap,
IN ULONG CpuNumber);
};
}
#endif /* __XTOSKRNL_KE_AFFINITY_HH */

View File

@@ -17,7 +17,16 @@ namespace KE
{
class Crash
{
private:
STATIC PKPROCESSOR_CONTROL_BLOCK FreezeOwner;
STATIC BOOLEAN KernelPanic;
STATIC KRUNLEVEL RunLevel;
public:
STATIC XTAPI VOID FreezeCurrentExecution(IN PKTRAP_FRAME TrapFrame,
IN PKEXCEPTION_FRAME ExceptionFrame);
STATIC XTAPI BOOLEAN FreezeExecution(IN PKTRAP_FRAME TrapFrame,
IN PKEXCEPTION_FRAME ExceptionFrame);
STATIC XTAPI VOID HaltSystem(VOID);
STATIC XTAPI VOID Panic(IN ULONG Code);
STATIC XTAPI VOID Panic(IN ULONG Code,
@@ -25,6 +34,8 @@ namespace KE
IN ULONG_PTR Parameter2,
IN ULONG_PTR Parameter3,
IN ULONG_PTR Parameter4);
STATIC XTAPI BOOLEAN SystemCrashed(VOID);
STATIC XTAPI VOID ThawExecution(IN BOOLEAN Interrupts);
};
}

View File

@@ -18,7 +18,9 @@ namespace KE
class Dispatcher
{
public:
STATIC XTAPI VOID EnterIdleLoop(VOID);
STATIC XTFASTCALL VOID ExitDispatcher(IN KRUNLEVEL OldRunLevel);
STATIC XTCDECL VOID HandleDispatchInterrupt(IN PKTRAP_FRAME TrapFrame);
STATIC XTFASTCALL BOOLEAN SwitchContext(IN PKTHREAD CurrentThread,
IN KRUNLEVEL RunLevel);
STATIC XTAPI VOID UpdateRunTime(IN PKTRAP_FRAME TrapFrame,

View File

@@ -19,18 +19,27 @@ namespace KE
{
private:
KSPIN_LOCK_QUEUE_LEVEL QueuedLockLevel;
BOOLEAN Owned;
public:
QueuedSpinLockGuard(IN OUT KSPIN_LOCK_QUEUE_LEVEL LockLevel)
QueuedSpinLockGuard(IN OUT KSPIN_LOCK_QUEUE_LEVEL LockLevel,
IN BOOLEAN Acquire = TRUE)
{
QueuedLockLevel = LockLevel;
Owned = Acquire;
if(Owned)
{
KE::SpinLock::AcquireQueuedSpinLock(QueuedLockLevel);
}
}
~QueuedSpinLockGuard()
{
if(Owned)
{
KE::SpinLock::ReleaseQueuedSpinLock(QueuedLockLevel);
}
}
QueuedSpinLockGuard(const QueuedSpinLockGuard&) = delete;
QueuedSpinLockGuard& operator=(const QueuedSpinLockGuard&) = delete;
@@ -40,18 +49,27 @@ namespace KE
{
private:
PKSPIN_LOCK Lock;
BOOLEAN Owned;
public:
SpinLockGuard(IN OUT PKSPIN_LOCK SpinLock)
SpinLockGuard(IN OUT PKSPIN_LOCK SpinLock,
IN BOOLEAN Acquire = TRUE)
{
Lock = SpinLock;
Owned = Acquire;
if(Owned)
{
KE::SpinLock::AcquireSpinLock(Lock);
}
}
~SpinLockGuard()
{
if(Owned)
{
KE::SpinLock::ReleaseSpinLock(Lock);
}
}
SpinLockGuard(const SpinLockGuard&) = delete;
SpinLockGuard& operator=(const SpinLockGuard&) = delete;

View File

@@ -0,0 +1,31 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/includes/ke/ipi.hh
* DESCRIPTION: Interprocessor interrupt support
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#ifndef __XTOSKRNL_KE_IPI_HH
#define __XTOSKRNL_KE_IPI_HH
#include <xtos.hh>
/* Kernel Library */
namespace KE
{
class Ipi
{
public:
STATIC XTCDECL VOID HandleIpiInterrupt(IN PKTRAP_FRAME TrapFrame);
STATIC XTAPI BOOLEAN HandleIpiService(IN PKTRAP_FRAME TrapFrame,
IN PKEXCEPTION_FRAME ExceptionFrame);
STATIC XTAPI VOID SendBroadcastIpi(IN ULONG Request,
IN BOOLEAN Self);
STATIC XTAPI VOID SendIpi(IN ULONG Request,
IN PKAFFINITY_MAP TargetSet);
};
}
#endif /* __XTOSKRNL_KE_IPI_HH */

View File

@@ -21,10 +21,13 @@ namespace KE
STATIC EPROCESS InitialProcess;
public:
STATIC XTAPI PKPROCESS GetIdleProcess(VOID);
STATIC XTAPI PEPROCESS GetInitialProcess(VOID);
STATIC XTAPI XTSTATUS InitializeIdleProcess(IN OUT PKPROCESS IdleProcess,
IN PULONG_PTR DirectoryTable);
STATIC XTAPI VOID InitializeProcess(IN OUT PKPROCESS Process,
IN KPRIORITY Priority,
IN KAFFINITY Affinity,
IN PKAFFINITY_MAP AffinityMap,
IN PULONG_PTR DirectoryTable,
IN BOOLEAN Alignment);
};

View File

@@ -24,6 +24,7 @@ namespace KE
private:
STATIC XTAPI VOID BootstrapKernel(VOID);
STATIC XTAPI VOID InitializeInterruptHandlers(VOID);
STATIC XTAPI VOID InitializeKernel(VOID);
};
}

View File

@@ -22,6 +22,10 @@ namespace KE
public:
STATIC XTAPI PETHREAD GetInitialThread(VOID);
STATIC XTAPI XTSTATUS InitializeIdleThread(IN PKPROCESS IdleProcess,
IN OUT PKTHREAD IdleThread,
IN PKPROCESSOR_CONTROL_BLOCK Prcb,
IN PVOID Stack);
STATIC XTAPI XTSTATUS InitializeThread(IN PKPROCESS Process,
IN OUT PKTHREAD Thread,
IN PKSYSTEM_ROUTINE SystemRoutine,

View File

@@ -26,12 +26,25 @@ namespace KE
STATIC XTAPI PKPROCESSOR_CONTROL_BLOCK GetCurrentProcessorControlBlock(VOID);
STATIC XTAPI ULONG GetCurrentProcessorNumber(VOID);
STATIC XTAPI PKTHREAD GetCurrentThread(VOID);
STATIC XTAPI ULONG GetInstalledCpus(VOID);
STATIC XTAPI PKPROCESSOR_BLOCK GetProcessorBlock(IN ULONG CpuNumber);
STATIC XTAPI XTSTATUS InitializeProcessorBlocks();
STATIC XTAPI VOID RegisterHardwareId(IN ULONG HardwareId);
STATIC XTAPI VOID RegisterProcessorBlock(ULONG CpuNumber,
PKPROCESSOR_BLOCK ProcessorBlock);
STATIC XTAPI VOID SaveProcessorState(OUT PKPROCESSOR_STATE CpuState);
STATIC XTAPI VOID RestoreProcessorContext(IN OUT PKTRAP_FRAME TrapFrame,
IN OUT PKEXCEPTION_FRAME ExceptionFrame,
IN PCONTEXT ContextFrame,
IN ULONG ContextFlags);
STATIC XTAPI VOID RestoreProcessorControlState(IN PKPROCESSOR_STATE CpuState);
STATIC XTAPI VOID RestoreProcessorState(OUT PKTRAP_FRAME TrapFrame,
OUT PKEXCEPTION_FRAME ExceptionFrame);
STATIC XTAPI VOID SaveProcessorContext(IN PKTRAP_FRAME TrapFrame,
IN PKEXCEPTION_FRAME ExceptionFrame,
IN OUT PCONTEXT ContextRecord);
STATIC XTAPI VOID SaveProcessorControlState(OUT PKPROCESSOR_STATE CpuState);
STATIC XTAPI VOID SaveProcessorState(IN PKTRAP_FRAME TrapFrame,
IN PKEXCEPTION_FRAME ExceptionFrame);
};
}

View File

@@ -27,18 +27,27 @@ namespace KE
{
private:
KRUNLEVEL PreviousRunLevel;
BOOLEAN Switched;
public:
LowerRunLevel(KRUNLEVEL RunLevel)
LowerRunLevel(IN KRUNLEVEL RunLevel,
IN BOOLEAN ChangeLevel = TRUE)
{
PreviousRunLevel = KE::RunLevel::GetCurrentRunLevel();
Switched = ChangeLevel;
if(Switched)
{
KE::RunLevel::LowerRunLevel(RunLevel);
}
}
~LowerRunLevel()
{
if(Switched)
{
KE::RunLevel::RaiseRunLevel(PreviousRunLevel);
}
}
LowerRunLevel(const LowerRunLevel&) = delete;
LowerRunLevel& operator=(const LowerRunLevel&) = delete;
@@ -48,18 +57,27 @@ namespace KE
{
private:
KRUNLEVEL PreviousRunLevel;
BOOLEAN Switched;
public:
RaiseRunLevel(KRUNLEVEL RunLevel)
RaiseRunLevel(IN KRUNLEVEL RunLevel,
IN BOOLEAN ChangeLevel = TRUE)
{
PreviousRunLevel = KE::RunLevel::GetCurrentRunLevel();
Switched = ChangeLevel;
if(Switched)
{
KE::RunLevel::RaiseRunLevel(RunLevel);
}
}
~RaiseRunLevel()
{
if(Switched)
{
KE::RunLevel::LowerRunLevel(PreviousRunLevel);
}
}
RaiseRunLevel(const RaiseRunLevel&) = delete;
RaiseRunLevel& operator=(const RaiseRunLevel&) = delete;

View File

@@ -0,0 +1,25 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/includes/ke/sysserv.hh
* DESCRIPTION: System Services Descriptor Table
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#ifndef __XTOSKRNL_KE_SYSSERV_HH
#define __XTOSKRNL_KE_SYSSERV_HH
#include <xtos.hh>
/* Kernel Library */
namespace KE
{
class SystemServices
{
public:
STATIC XTAPI PKSERVICE_DESCRIPTOR_TABLE GetSystemServicesDescriptorTable(VOID);
};
}
#endif /* __XTOSKRNL_KE_SYSSERV_HH */

View File

@@ -17,6 +17,9 @@ namespace KE
{
class Timer
{
private:
STATIC LIST_ENTRY TimerTableListHead[KTIMER_TABLE_SIZE];
public:
STATIC XTAPI BOOLEAN CancelTimer(IN PKTIMER Timer);
STATIC XTAPI VOID ClearTimer(IN PKTIMER Timer);
@@ -28,6 +31,9 @@ namespace KE
IN LARGE_INTEGER DueTime,
IN LONG Period,
IN PKDPC Dpc);
STATIC XTAPI VOID VerifySystemTimerExpiration(IN PKPROCESSOR_CONTROL_BLOCK Prcb,
IN PKTRAP_FRAME TrapFrame,
IN LARGE_INTEGER Time);
private:
STATIC XTAPI VOID RemoveTimer(IN OUT PKTIMER Timer);

View File

@@ -20,6 +20,8 @@ namespace MM
private:
STATIC LOADER_MEMORY_DESCRIPTOR HardwareAllocationDescriptors[MM_HARDWARE_ALLOCATION_DESCRIPTORS];
STATIC PVOID HardwareHeapStart;
STATIC PHYSICAL_ADDRESS LowMemoryPhysicalAddress;
STATIC PVOID LowMemoryVirtualAddress;
STATIC ULONG UsedHardwareAllocationDescriptors;
public:
@@ -27,12 +29,19 @@ namespace MM
IN BOOLEAN Aligned,
IN ULONGLONG MaximumAddress,
OUT PPHYSICAL_ADDRESS Buffer);
STATIC XTAPI XTSTATUS AllocateRealModeMemory(IN PFN_NUMBER PageCount,
OUT PVOID *MemoryAddress);
STATIC XTAPI XTSTATUS AllocateLowMemory(OUT PPHYSICAL_ADDRESS PhysicalAddress,
OUT PVOID *VirtualAddress);
STATIC XTAPI ULONG CalculateRealModeAllocationPages(IN ULONG TrampolineCodeSize);
STATIC XTAPI XTSTATUS FreeHardwareMemory(IN PHYSICAL_ADDRESS PhysicalAddress,
IN PFN_NUMBER PageCount);
STATIC XTAPI XTSTATUS FreeRealModeMemory(IN PVOID VirtualAddress,
IN PFN_NUMBER PageCount);
STATIC XTAPI XTSTATUS MapHardwareMemory(IN PHYSICAL_ADDRESS PhysicalAddress,
IN PFN_NUMBER PageCount,
IN BOOLEAN FlushTlb,
OUT PVOID *VirtualAddress);
STATIC XTAPI XTSTATUS MapRealModeMemory(IN PHYSICAL_ADDRESS PhysicalAddress,
IN ULONG Size);
STATIC XTAPI VOID MarkHardwareMemoryWriteThrough(IN PVOID VirtualAddress,
IN PFN_NUMBER PageCount);
STATIC XTAPI VOID RemapHardwareMemory(IN PVOID VirtualAddress,
@@ -41,6 +50,8 @@ namespace MM
STATIC XTAPI XTSTATUS UnmapHardwareMemory(IN PVOID VirtualAddress,
IN PFN_NUMBER PageCount,
IN BOOLEAN FlushTlb);
STATIC XTAPI VOID UnmapRealModeMemory(IN PHYSICAL_ADDRESS PhysicalAddress,
IN ULONG Size);
};
}

View File

@@ -12,7 +12,7 @@
#include <xtos.hh>
/* Runtime Library */
/* Power Management */
namespace PO
{
class Idle

18
xtoskrnl/includes/ps.hh Normal file
View File

@@ -0,0 +1,18 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/includes/ps.hh
* DESCRIPTION: Process and thread management
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#ifndef __XTOSKRNL_PS_HH
#define __XTOSKRNL_PS_HH
#include <xtos.hh>
#include <ps/process.hh>
#include <ps/thread.hh>
#endif /* __XTOSKRNL_PS_HH */

View File

@@ -0,0 +1,25 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/includes/ps/process.hh
* DESCRIPTION: Process Management
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#ifndef __XTOSKRNL_PS_PROCESS_HH
#define __XTOSKRNL_PS_PROCESS_HH
#include <xtos.hh>
/* Process and thread management */
namespace PS
{
class Process
{
public:
STATIC XTAPI XTSTATUS CreateIdleProcess(IN PKPROCESSOR_CONTROL_BLOCK Prcb);
};
}
#endif /* __XTOSKRNL_PS_PROCESS_HH */

View File

@@ -0,0 +1,26 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/includes/ps/thread.hh
* DESCRIPTION: Thread Management
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#ifndef __XTOSKRNL_PS_THREAD_HH
#define __XTOSKRNL_PS_THREAD_HH
#include <xtos.hh>
/* Process and thread management */
namespace PS
{
class Thread
{
public:
STATIC XTAPI XTSTATUS CreateIdleThread(IN PKPROCESSOR_CONTROL_BLOCK Prcb,
IN PVOID Stack);
};
}
#endif /* __XTOSKRNL_PS_THREAD_HH */

View File

@@ -24,4 +24,5 @@
#include <ke.hh>
#include <mm.hh>
#include <po.hh>
#include <ps.hh>
#include <rtl.hh>

View File

@@ -0,0 +1,36 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/kd/amd64/debug.cc
* DESCRIPTION: Kernel Debugger
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#include <xtos.hh>
/**
* Transfers active control to a previously frozen processor.
*
* @return This routine returns a value indicating how execution should proceed after the debugging session concludes.
*
* @since XT 1.0
*/
XTAPI
KCONTINUE_STATUS
KD::Debugger::SwitchProcessor(VOID)
{
EXCEPTION_RECORD ExceptionRecord;
PKPROCESSOR_CONTROL_BLOCK Prcb;
/* Get processor control block */
Prcb = KE::Processor::GetCurrentProcessorControlBlock();
/* Construct an exception record */
ExceptionRecord.ExceptionAddress = (PVOID)&Prcb->ProcessorState.ContextFrame.Rip;
ExceptionRecord.ExceptionCode = STATUS_WAKE_SYSTEM_DEBUGGER;
ExceptionRecord.ExceptionRecord = &ExceptionRecord;
/* Pass the synthetic exception and the processor context to the debugger */
return (KCONTINUE_STATUS)ProcessCpuStateChange(&ExceptionRecord, &Prcb->ProcessorState.ContextFrame, FALSE);
}

View File

@@ -9,6 +9,9 @@
#include <xtos.hh>
/* Debugger active flag */
BOOLEAN KD::Debugger::Active;
/* Debug I/O spinlock */
KSPIN_LOCK KD::DebugIo::DebugIoLock;

View File

@@ -57,12 +57,16 @@ VOID
KD::DebugIo::DbgPrint(PCWSTR Format,
VA_LIST Arguments)
{
PLIST_ENTRY DispatchTableEntry;
PKD_DISPATCH_TABLE DispatchTable;
PLIST_ENTRY DispatchTableEntry;
BOOLEAN BypassLocks;
/* Raise runlevel and acquire the Debug I/O lock */
KE::RaiseRunLevel RunLevel(HIGH_LEVEL);
KE::SpinLockGuard SpinLock(&DebugIoLock);
/* Evaluate if the system is currently in a critical or debugging state */
BypassLocks = (KE::Crash::SystemCrashed() || KD::Debugger::DebuggerActive());
/* Conditionally raise runlevel and acquire the Debug I/O lock */
KE::RaiseRunLevel RunLevel(HIGH_LEVEL, !BypassLocks);
KE::SpinLockGuard SpinLock(&DebugIoLock, !BypassLocks);
/* Iterate over all registered debug providers */
DispatchTableEntry = Providers.Flink;

74
xtoskrnl/kd/debug.cc Normal file
View File

@@ -0,0 +1,74 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/kd/debug.cc
* DESCRIPTION: Kernel Debugger
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#include <xtos.hh>
/**
* Determines whether the interactive kernel debugger is currently active and controlling the execution flow.
*
* @return This routine returns TRUE if the kernel debugger is active, or FALSE otherwise.
*
* @since XT 1.0
*/
XTAPI
BOOLEAN
KD::Debugger::DebuggerActive(VOID)
{
return Active;
}
/**
* Serves as the primary entry point for the interactive kernel debugger.
*
* @param TrapFrame
* Supplies a pointer to the processor's trap frame captured at the moment the breakpoint or exception occurred.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
KD::Debugger::EnterDebugger(IN PKTRAP_FRAME TrapFrame)
{
/* Mark the debugger as active */
Active = TRUE;
/* Print debug message and enter an infinite loop */
DebugPrint(L"\n\n*** Entered KDebugger ***\n");
for(;;);
/* Mark the debugger as inactive */
Active = FALSE;
}
/**
* Processes a processor state change and acts as the primary event loop for the debugger.
*
* @param ExceptionRecord
* Supplies a pointer to the exception record that triggered the state change.
*
* @param Context
* Supplies a pointer to the processor's context frame.
*
* @param SecondChance
* Supplies a boolean value indicating whether this is a second-chance exception.
*
* @return This routine returns TRUE if the exception was handled by the debugger, or FALSE otherwise.
*
* @since XT 1.0
*/
XTAPI
BOOLEAN
KD::Debugger::ProcessCpuStateChange(IN PEXCEPTION_RECORD ExceptionRecord,
IN OUT PCONTEXT Context,
IN BOOLEAN SecondChance)
{
return FALSE;
}

36
xtoskrnl/kd/i686/debug.cc Normal file
View File

@@ -0,0 +1,36 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/kd/i686/debug.cc
* DESCRIPTION: Kernel Debugger
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#include <xtos.hh>
/**
* Transfers active control to a previously frozen processor.
*
* @return This routine returns a value indicating how execution should proceed after the debugging session concludes.
*
* @since XT 1.0
*/
XTAPI
KCONTINUE_STATUS
KD::Debugger::SwitchProcessor(VOID)
{
EXCEPTION_RECORD ExceptionRecord;
PKPROCESSOR_CONTROL_BLOCK Prcb;
/* Get processor control block */
Prcb = KE::Processor::GetCurrentProcessorControlBlock();
/* Construct an exception record */
ExceptionRecord.ExceptionAddress = (PVOID)&Prcb->ProcessorState.ContextFrame.Eip;
ExceptionRecord.ExceptionCode = STATUS_WAKE_SYSTEM_DEBUGGER;
ExceptionRecord.ExceptionRecord = &ExceptionRecord;
/* Pass the synthetic exception and the processor context to the debugger */
return (KCONTINUE_STATUS)ProcessCpuStateChange(&ExceptionRecord, &Prcb->ProcessorState.ContextFrame, FALSE);
}

562
xtoskrnl/ke/affinity.cc Normal file
View File

@@ -0,0 +1,562 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/ke/affinity.cc
* DESCRIPTION: XT kernel processor affinity management support
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#include <xtos.hh>
/**
* Atomically sets the target processor's affinity bit within the affinity map.
*
* @param AffinityMap
* Supplies a pointer to the affinity map to be modified.
*
* @param CpuNumber
* Supplies the logical processor number to include in the affinity map.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTFASTCALL
VOID
KE::Affinity::AtomicSetProcessorAffinity(IN OUT PKAFFINITY_MAP AffinityMap,
IN ULONG CpuNumber)
{
/* Verify that the target processor falls within the allocated map boundaries */
if((CpuNumber / 64) < AffinityMap->Size)
{
/* Atomically set the target CPU bit */
RTL::Atomic::Or64((PLONG_PTR)&AffinityMap->Bitmap[CpuNumber / 64], ((KAFFINITY)1 << (CpuNumber % 64)));
}
}
/**
* Computes the memory size required to allocate an affinity map.
*
* @param CpuCount
* Supplies the total number of logical processors the map needs to support.
*
* @param RequiredMapSize
* Supplies a pointer to a variable that receives the 8-byte aligned allocation size in bytes.
*
* @param RequiredBlockCount
* Supplies a pointer to a variable that receives the number of KAFFINITY blocks required to hold all CPUs.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTFASTCALL
VOID
KE::Affinity::CalculateAffinityMapSize(IN ULONG CpuCount,
OUT PULONG RequiredMapSize,
OUT PULONG RequiredBlockCount)
{
ULONG AffinitySize, MapSize;
/* Calculate the required number of blocks and the total structure size */
AffinitySize = (CpuCount + 63) / 64;
MapSize = sizeof(KAFFINITY_MAP) + (AffinitySize * sizeof(KAFFINITY));
/* Check if an allocation size is required */
if(RequiredMapSize != NULLPTR)
{
/* Return the required allocation bytes aligned to an 8-byte boundary */
*RequiredMapSize = (MapSize + 7) & ~7;
}
/* Check if a block count is required */
if(RequiredBlockCount != NULLPTR)
{
/* Return the required logical block count */
*RequiredBlockCount = AffinitySize;
}
}
/**
* Checks whether a specific processor is included in the affinity map.
*
* @param AffinityMap
* Supplies a pointer to the affinity map to query.
*
* @param CpuNumber
* Supplies the logical processor number to test.
*
* @return This routine returns TRUE if the processor's bit is set in the map, or FALSE otherwise.
*
* @since XT 1.0
*/
XTFASTCALL
BOOLEAN
KE::Affinity::CheckProcessorAffinity(IN PKAFFINITY_MAP AffinityMap,
IN ULONG CpuNumber)
{
/* Verify that the target processor falls within the allocated map boundaries */
if((CpuNumber / 64) < AffinityMap->Size)
{
/* Isolate and test the specific bit corresponding to the target CPU */
return (AffinityMap->Bitmap[CpuNumber / 64] & ((KAFFINITY)1 << (CpuNumber % 64))) != 0;
}
/* Return FALSE if the requested CPU exceeds the map capacity */
return FALSE;
}
/**
* Clears all processor bindings from the given affinity map.
*
* @param AffinityMap
* Supplies a pointer to the affinity map to be cleared.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTFASTCALL
VOID
KE::Affinity::ClearAffinityMap(IN OUT PKAFFINITY_MAP AffinityMap)
{
/* Zero out the entire bitmap */
RTL::Memory::ZeroMemory(AffinityMap->Bitmap, AffinityMap->Size * sizeof(KAFFINITY));
}
/**
* Clears the affinity bit for a specified processor. This is a non-atomic operation.
*
* @param AffinityMap
* Supplies a pointer to the affinity map to be modified.
*
* @param CpuNumber
* Supplies the logical processor number to exclude from the affinity map.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTFASTCALL
VOID
KE::Affinity::ClearProcessorAffinity(IN OUT PKAFFINITY_MAP AffinityMap,
IN ULONG CpuNumber)
{
/* Verify that the target processor falls within the allocated map boundaries */
if((CpuNumber / 64) < AffinityMap->Size)
{
/* Clear the target CPU bit in the affinity map */
AffinityMap->Bitmap[CpuNumber / 64] &= ~((KAFFINITY)1 << (CpuNumber % 64));
}
}
/**
* Copies the topological layout and processor bindings from a source affinity map to a destination map.
*
* @param Destination
* Supplies a pointer to the target affinity map that will receive the copied data.
*
* @param Source
* Supplies a pointer to the source affinity map containing the active processor bindings.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
XTSTATUS
KE::Affinity::CopyAffinity(OUT PKAFFINITY_MAP Destination,
IN PKAFFINITY_MAP Source)
{
ULONG Index;
/* Validate that the destination map can accommodate the source topology */
if(Destination->Size < Source->Size)
{
/* Buffer overrun prevention */
return STATUS_BUFFER_TOO_SMALL;
}
/* Copy map metadata */
Destination->Reserved = Source->Reserved;
/* Copy the active affinity bitmasks */
for(Index = 0; Index < Source->Size; Index++)
{
/* Replicate the hardware topology bindings across all active array elements */
Destination->Bitmap[Index] = Source->Bitmap[Index];
}
/* Return success */
return STATUS_SUCCESS;
}
/**
* Allocates and initializes a new affinity map for the specified number of processors.
*
* @param CpuCount
* Supplies the total number of logical processors the map needs to support.
*
* @param AffinityMap
* Supplies a pointer to a variable that receives the address of the newly allocated and initialized map.
*
* @return This routine returns a status code indicating the success or failure of the operation.
*
* @since XT 1.0
*/
XTAPI
XTSTATUS
KE::Affinity::CreateAffinityMap(IN ULONG CpuCount,
OUT PKAFFINITY_MAP* AffinityMap)
{
PKAFFINITY_MAP AllocatedMap;
ULONG BlockCount, MapSize;
XTSTATUS Status;
/* Query the required allocation size and internal block count */
KE::Affinity::CalculateAffinityMapSize(CpuCount, &MapSize, &BlockCount);
/* Allocate the memory block from the specified pool */
Status = MM::Allocator::AllocatePool(NonPagedPool, MapSize, (PVOID*)&AllocatedMap);
if(Status != STATUS_SUCCESS)
{
/* Allocation failed, return status code */
return Status;
}
/* Zero the memory to ensure all processor bits are initially cleared */
RTL::Memory::ZeroMemory(AllocatedMap, MapSize);
/* Initialize the internal metadata required by iteration and validation routines */
AllocatedMap->Size = BlockCount;
/* Return the constructed map to the caller */
*AffinityMap = AllocatedMap;
/* Return success */
return STATUS_SUCCESS;
}
/**
* Frees a previously allocated affinity map and returns its memory to the pool.
*
* @param AffinityMap
* Supplies a pointer to the affinity map to be freed and destroyed.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
KE::Affinity::DestroyAffinityMap(IN PKAFFINITY_MAP AffinityMap)
{
/* Ensure the map pointer is valid */
if(AffinityMap != NULLPTR)
{
/* Free the memory block back to the kernel pool */
MM::Allocator::FreePool((PVOID)AffinityMap);
}
}
/**
* Locates the next available logical processor to the left (higher topological index) of a specified seed.
*
* @param ThreadSeed
* Supplies the logical processor index used as the starting point for the upward search.
*
* @param AffinityMap
* Supplies a pointer to the extended affinity map defining the permitted processors.
*
* @return This routine returns the absolute topological index of the selected processor.
*
* @since XT 1.0
*/
XTAPI
ULONG
KE::Affinity::FindNextLeftSetProcessor(IN ULONG ThreadSeed,
IN PKAFFINITY_MAP AffinityMap)
{
ULONG BitIndex, BitsPerMask, Index, StartBit, StartIndex;
KAFFINITY Mask;
/* Define the architectural bit width of a single affinity mask */
BitsPerMask = sizeof(KAFFINITY) * 8;
/* Prevent division by zero and out-of-bounds access if the topology map is uninitialized or empty */
if(AffinityMap->Size == 0)
{
/* Fallback to the bootstrap processor */
return 0;
}
/* Calculate the target array index and bit offset based on the thread seed */
StartIndex = (ThreadSeed / BitsPerMask) % AffinityMap->Size;
StartBit = ThreadSeed % BitsPerMask;
/* Isolate the segment of the current affinity mask strictly to the left */
if(StartBit == (BitsPerMask - 1))
{
/* Prevent undefined behavior when shifting by the total architectural bit width */
Mask = 0;
}
else
{
/* Mask out the seed bit and all bits below it */
Mask = AffinityMap->Bitmap[StartIndex] & (~((KAFFINITY)0) << (StartBit + 1));
}
/* Evaluate if any allowed processors exist in the higher portion of the current mask */
if(Mask != 0)
{
/* Locate the rightmost set bit within this masked subset */
if(AR::CpuFunctions::ScanForwardBit(&BitIndex, Mask))
{
/* Return the absolute topological index of the located processor */
return (StartIndex * BitsPerMask) + BitIndex;
}
}
/* Ascend through the subsequent array elements in the map */
for(Index = StartIndex + 1; Index < AffinityMap->Size; Index++)
{
/* Load the complete processor mask for the current array boundary */
Mask = AffinityMap->Bitmap[Index];
/* Check if this segment contains any active processor bindings */
if(Mask != 0)
{
/* Find the lowest available processor within this array element */
if(AR::CpuFunctions::ScanForwardBit(&BitIndex, Mask))
{
/* Return the absolute topological index of the located processor */
return (Index * BitsPerMask) + BitIndex;
}
}
}
/* Wrap around and scan the entire map from the bottom to find the lowest globally permitted processor */
for(Index = 0; Index < AffinityMap->Size; Index++)
{
/* Load the complete processor mask for the current array boundary */
Mask = AffinityMap->Bitmap[Index];
/* Check if this segment contains any active processor bindings */
if(Mask != 0)
{
/* Find the lowest available processor within this array element */
if(AR::CpuFunctions::ScanForwardBit(&BitIndex, Mask))
{
/* Return the absolute topological index of the located processor */
return (Index * BitsPerMask) + BitIndex;
}
}
}
/* Fallback to the bootstrap processor */
return 0;
}
/**
* Locates the next available logical processor to the right (lower topological index) of a specified seed.
*
* @param ThreadSeed
* Supplies the logical processor index used as the starting point for the downward search.
*
* @param AffinityMap
* Supplies a pointer to the extended affinity map defining the permitted processors.
*
* @return This routine returns the absolute topological index of the selected processor.
*
* @since XT 1.0
*/
XTAPI
ULONG
KE::Affinity::FindNextRightSetProcessor(IN ULONG ThreadSeed,
IN PKAFFINITY_MAP AffinityMap)
{
ULONG BitIndex, BitsPerMask, StartBit, StartIndex;
KAFFINITY Mask;
LONG Index;
/* Define the architectural bit width of a single affinity mask */
BitsPerMask = sizeof(KAFFINITY) * 8;
/* Prevent division by zero and out-of-bounds access if the topology map is uninitialized or empty */
if(AffinityMap->Size == 0)
{
/* Fallback to the bootstrap processor */
return 0;
}
/* Calculate the target array index and bit offset based on the seed */
StartIndex = (ThreadSeed / BitsPerMask) % AffinityMap->Size;
StartBit = ThreadSeed % BitsPerMask;
/* Isolate the segment of the current affinity mask strictly to the right */
Mask = AffinityMap->Bitmap[StartIndex] & (((KAFFINITY)1 << StartBit) - 1);
/* Evaluate if any allowed processors exist in the lower portion of the current mask */
if(Mask != 0)
{
/* Locate the leftmost set bit within this masked subset */
if(AR::CpuFunctions::ScanReverseBit(&BitIndex, Mask))
{
/* Return the absolute topological index of the located processor */
return (StartIndex * BitsPerMask) + BitIndex;
}
}
/* Descend through the preceding array elements in the map */
for(Index = (LONG)StartIndex - 1; Index >= 0; Index--)
{
/* Load the complete processor mask for the current array boundary */
Mask = AffinityMap->Bitmap[Index];
/* Check if this segment contains any active processor bindings */
if(Mask != 0)
{
/* Find the highest available processor within this array element */
if(AR::CpuFunctions::ScanReverseBit(&BitIndex, Mask))
{
/* Return the absolute topological index of the located processor */
return ((ULONG)Index * BitsPerMask) + BitIndex;
}
}
}
/* Wrap around and scan the entire map from the top to find the highest globally permitted processor */
for(Index = (LONG)AffinityMap->Size - 1; Index >= 0; Index--)
{
/* Load the complete processor mask for the current array boundary */
Mask = AffinityMap->Bitmap[Index];
/* Check if this segment contains any active processor bindings */
if(Mask != 0)
{
/* Find the highest available processor within this array element */
if(AR::CpuFunctions::ScanReverseBit(&BitIndex, Mask))
{
/* Return the absolute topological index of the located processor */
return ((ULONG)Index * BitsPerMask) + BitIndex;
}
}
}
/* Fallback to the bootstrap processor */
return 0;
}
/**
* Initializes a caller-allocated affinity map structure.
*
* @param AffinityMap
* Supplies a pointer to the caller-allocated buffer to be initialized.
*
* @param BufferSize
* Supplies the size, in bytes, of the provided buffer.
*
* @return This routine returns a status code indicating the success or failure of the operation.
*
* @since XT 1.0
*/
XTAPI
XTSTATUS
KE::Affinity::InitializeAffinityMap(IN OUT PKAFFINITY_MAP AffinityMap,
IN ULONG BufferSize)
{
ULONG Cpus, RequiredBlocks, RequiredSize;
/* Get the number of available CPUs */
Cpus = KE::Processor::GetInstalledCpus();
/* Query the required size in bytes and the architectural block count */
KE::Affinity::CalculateAffinityMapSize(Cpus, &RequiredSize, &RequiredBlocks);
/* Validate that the provided buffer is large enough to hold the structure */
if(BufferSize < RequiredSize)
{
/* Buffer overrun prevention */
return STATUS_BUFFER_TOO_SMALL;
}
/* Zero only the required portion of the memory to clear any garbage data */
RTL::Memory::ZeroMemory(AffinityMap, RequiredSize);
/* Initialize the internal metadata required by iteration routines */
AffinityMap->Reserved = 0;
AffinityMap->Size = RequiredBlocks;
/* Return success */
return STATUS_SUCCESS;
}
/**
* Populates the affinity map with all available processors.
*
* @param AffinityMap
* Supplies a pointer to the affinity map to be fully populated.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTFASTCALL
VOID
KE::Affinity::SetAllProcessorsAffinity(IN OUT PKAFFINITY_MAP AffinityMap)
{
ULONG Cpus, Index;
/* Get the number of available CPUs */
Cpus = KE::Processor::GetInstalledCpus();
/* Iterate through all allocated blocks in the map */
for(Index = 0; Index < AffinityMap->Size; Index++)
{
/* Evaluate if the remaining logical processors fully saturate the current block */
if(Cpus >= 64)
{
/* Set all 64 bits and decrement the remaining count */
AffinityMap->Bitmap[Index] = ~((KAFFINITY)0);
Cpus -= 64;
}
else if(Cpus > 0)
{
/* Generate a partial bitmask for the tail end of the processors */
AffinityMap->Bitmap[Index] = (((KAFFINITY)1 << Cpus) - 1);
Cpus = 0;
}
else
{
/* Ensure any remaining blocks are safely zeroed */
AffinityMap->Bitmap[Index] = 0;
}
}
}
/**
* Sets the affinity bit for a specified processor. This is a non-atomic operation.
*
* @param AffinityMap
* Supplies a pointer to the affinity map to be modified.
*
* @param CpuNumber
* Supplies the logical processor number to include in the affinity map.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTFASTCALL
VOID
KE::Affinity::SetProcessorAffinity(IN OUT PKAFFINITY_MAP AffinityMap,
IN ULONG CpuNumber)
{
/* Verify that the target processor falls within the allocated map boundaries */
if((CpuNumber / 64) < AffinityMap->Size)
{
/* Set the target CPU bit in the affinity map */
AffinityMap->Bitmap[CpuNumber / 64] |= ((KAFFINITY)1 << (CpuNumber % 64));
}
}

View File

@@ -22,13 +22,12 @@
*
* @since XT 1.0
*/
XTASSEMBLY
XTFASTCALL
BOOLEAN
KE::Dispatcher::SwitchContext(IN PKTHREAD CurrentThread,
IN KRUNLEVEL RunLevel)
{
BOOLEAN PendingApc;
/* Save non-volatile and XMM registers to the exception frame, align the stack and invoke the switch routine */
__asm__ volatile("subq %[ExFrameSize], %%rsp\n"
"movq %%rbp, %c[ExRbp](%%rsp)\n"
@@ -69,10 +68,9 @@ KE::Dispatcher::SwitchContext(IN PKTHREAD CurrentThread,
"movdqa %c[ExXmm14](%%rsp), %%xmm14\n"
"movdqa %c[ExXmm15](%%rsp), %%xmm15\n"
"addq %[ExFrameSize], %%rsp\n"
: "=a" (PendingApc)
: "c" (CurrentThread),
"d" (RunLevel),
[ExFrameSize] "i" (sizeof(KEXCEPTION_FRAME) - 8),
"ret\n"
:
: [ExFrameSize] "i" (sizeof(KEXCEPTION_FRAME) - 8),
[ExR12] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, R12)),
[ExR13] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, R13)),
[ExR14] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, R14)),
@@ -93,9 +91,6 @@ KE::Dispatcher::SwitchContext(IN PKTHREAD CurrentThread,
[ExXmm15] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Xmm15)),
[SwitchRoutine] "i" (SwitchThreadStack)
: "cc", "memory", "r8", "r9", "r10", "r11");
/* Return the APC status */
return PendingApc;
}
/**
@@ -134,13 +129,12 @@ KE::Dispatcher::SwitchThreadContext(IN PKTHREAD CurrentThread,
*
* @since XT 1.0
*/
XTASSEMBLY
XTFASTCALL
BOOLEAN
KE::Dispatcher::SwitchThreadStack(IN PKTHREAD CurrentThread,
IN KRUNLEVEL RunLevel)
{
BOOLEAN PendingApc;
/* Preserve MXCSR, synchronize with CPUs, switch stack and call the switch routine */
__asm__ volatile("pushq %%rbp\n"
"subq %[FrameSize], %%rsp\n"
@@ -160,10 +154,9 @@ KE::Dispatcher::SwitchThreadStack(IN PKTHREAD CurrentThread,
"ldmxcsr %c[SwMxCsr](%%rsp)\n"
"addq %[FrameSize], %%rsp\n"
"popq %%rbp\n"
: "=a" (PendingApc)
: "c" (CurrentThread),
"d" (RunLevel),
[FrameSize] "i" (FIELD_OFFSET(KSWITCH_FRAME, Rbp)),
"ret\n"
:
: [FrameSize] "i" (FIELD_OFFSET(KSWITCH_FRAME, Rbp)),
[PrcbcCurrentThread] "i" (FIELD_OFFSET(KPROCESSOR_BLOCK, Prcb.CurrentThread)),
[SwApcBypass] "i" (FIELD_OFFSET(KSWITCH_FRAME, ApcBypass)),
[SwMxCsr] "i" (FIELD_OFFSET(KSWITCH_FRAME, MxCsr)),
@@ -171,7 +164,4 @@ KE::Dispatcher::SwitchThreadStack(IN PKTHREAD CurrentThread,
[ThrdStack] "i" (FIELD_OFFSET(KTHREAD, KernelStack)),
[ThrdSwapBusy] "i" (FIELD_OFFSET(KTHREAD, SwapBusy))
: "cc", "memory", "r8", "r9", "r10", "r11");
/* Return the APC status */
return PendingApc;
}

View File

@@ -46,21 +46,30 @@ KE::KernelInit::BootstrapApplicationProcessor(IN PPROCESSOR_START_BLOCK StartBlo
PO::Idle::InitializeProcessorIdleState(ControlBlock);
/* Save processor state */
KE::Processor::SaveProcessorState(&ControlBlock->ProcessorState);
KE::Processor::SaveProcessorControlState(&ControlBlock->ProcessorState);
/* Initialize per-CPU spin lock queues */
KE::SpinLock::InitializeLockQueues();
/* Initialize interrupt handlers */
InitializeInterruptHandlers();
/* Lower to APC runlevel */
KE::RunLevel::LowerRunLevel(APC_LEVEL);
/* Initialize local clock for this CPU */
HL::Timer::InitializeLocalClock();
/* Enter infinite loop */
DebugPrint(L"KernelInit::BootstrapApplicationProcessor() finished for CPU #%lu. Entering infinite loop.\n",
/* Create and initialize IDLE thread */
PS::Thread::CreateIdleThread(ControlBlock, StartBlock->Stack);
/* Register DISPATCH interrupt handler */
HL::Irq::RegisterSystemInterruptHandler(APIC_VECTOR_DPC, KE::Dispatcher::HandleDispatchInterrupt);
/* Enter idle loop */
DebugPrint(L"KernelInit::BootstrapApplicationProcessor() finished for CPU #%lu. Entering IDLE loop.\n",
ControlBlock->CpuNumber);
KE::Crash::HaltSystem();
KE::Dispatcher::EnterIdleLoop();
}
/**
@@ -76,62 +85,65 @@ VOID
KE::KernelInit::BootstrapKernel(VOID)
{
PKPROCESSOR_CONTROL_BLOCK Prcb;
ULONG_PTR PageDirectory[2];
PKPROCESS CurrentProcess;
PKTHREAD CurrentThread;
/* Get processor control block and current thread */
/* Get processor control block */
Prcb = KE::Processor::GetCurrentProcessorControlBlock();
CurrentThread = KE::Processor::GetCurrentThread();
/* Get current process */
CurrentProcess = CurrentThread->ApcState.Process;
/* Initialize CPU power state structures */
PO::Idle::InitializeProcessorIdleState(Prcb);
/* Save processor state */
KE::Processor::SaveProcessorState(&Prcb->ProcessorState);
KE::Processor::SaveProcessorControlState(&Prcb->ProcessorState);
/* Initialize spin locks */
KE::SpinLock::InitializeAllLocks();
KE::SpinLock::InitializeLockQueues();
/* Initialize interrupt handlers */
InitializeInterruptHandlers();
/* Lower to APC runlevel */
KE::RunLevel::LowerRunLevel(APC_LEVEL);
/* Initialize XTOS kernel */
InitializeKernel();
/* Initialize Idle process */
PageDirectory[0] = 0;
PageDirectory[1] = 0;
KE::KProcess::InitializeProcess(CurrentProcess, 0, MAXULONG_PTR, PageDirectory, FALSE);
CurrentProcess->Quantum = MAXCHAR;
/* Initialize Idle thread */
KE::KThread::InitializeThread(CurrentProcess, CurrentThread, NULLPTR, NULLPTR, NULLPTR,
NULLPTR, NULLPTR, AR::ProcessorSupport::GetBootStack(), TRUE);
CurrentThread->NextProcessor = Prcb->CpuNumber;
CurrentThread->Priority = THREAD_HIGH_PRIORITY;
CurrentThread->State = Running;
CurrentThread->Affinity = (ULONG_PTR)1 << Prcb->CpuNumber;
CurrentThread->WaitRunLevel = DISPATCH_LEVEL;
CurrentProcess->ActiveProcessors |= (ULONG_PTR)1 << Prcb->CpuNumber;
/* Initialize Memory Manager */
MM::Manager::InitializeMemoryManager();
/* Enable shadow buffer for framebuffer */
HL::FrameBuffer::EnableShadowBuffer();
/* Create and initialize IDLE process */
PS::Process::CreateIdleProcess(Prcb);
/* Start all application processors */
KE::Processor::InitializeProcessorBlocks();
HL::Cpu::InitializeProcessorAffinity();
HL::Cpu::StartAllProcessors();
/* Enter infinite loop */
DebugPrint(L"KernelInit::BootstrapKernel() finished. Entering infinite loop.\n");
KE::Crash::HaltSystem();
/* Register DISPATCH interrupt handler */
HL::Irq::RegisterSystemInterruptHandler(APIC_VECTOR_DPC, KE::Dispatcher::HandleDispatchInterrupt);
/* Enter idle loop */
DebugPrint(L"KernelInit::BootstrapKernel() finished. Entering IDLE loop.\n");
KE::Dispatcher::EnterIdleLoop();
}
/**
* Initializes and registers the core system interrupt handlers.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
KE::KernelInit::InitializeInterruptHandlers(VOID)
{
/* Register interrupt handlers */
HL::Irq::RegisterSystemInterruptHandler(APIC_VECTOR_DPC, KE::Dispatcher::HandleDispatchInterrupt);
HL::Irq::RegisterSystemInterruptHandler(APIC_VECTOR_IPI, KE::Ipi::HandleIpiInterrupt);
}
/**
@@ -209,7 +221,7 @@ KE::KernelInit::SwitchBootStack(VOID)
__asm__ volatile("movq %[Stack], %%rsp\n"
"subq %[TotalSize], %%rsp\n"
"xorq %%rbp, %%rbp\n"
"jmp *%[TargetRoutine]\n"
"call *%[TargetRoutine]\n"
:
: [Stack] "r" (Stack),
[TargetRoutine] "r" (StartKernel),

View File

@@ -66,6 +66,21 @@ KE::Processor::GetCurrentThread(VOID)
return (PKTHREAD)AR::CpuFunctions::ReadGSQuadWord(FIELD_OFFSET(KPROCESSOR_BLOCK, Prcb.CurrentThread));
}
/**
* Retrieves the number of installed and enabled CPUs in the system.
*
* @return This routine returns the number of installed CPUs in the system.
*
* @since XT 1.0
*/
XTAPI
ULONG
KE::Processor::GetInstalledCpus(VOID)
{
/* Return number of installed CPUs */
return InstalledCpus;
}
/**
* Gets the processor block for the specified processor number.
*
@@ -122,6 +137,9 @@ KE::Processor::InitializeProcessorBlocks()
/* Zero the array initially */
RTL::Memory::ZeroMemory(ProcessorBlocks, InstalledCpus * sizeof(PKPROCESSOR_BLOCK));
/* Register the processor block for the BSP processor */
KE::Processor::RegisterProcessorBlock(0, KE::Processor::GetCurrentProcessorBlock());
/* Return success */
return STATUS_SUCCESS;
}
@@ -178,10 +196,20 @@ KE::Processor::RegisterProcessorBlock(ULONG CpuNumber,
}
/**
* Saves the current processor state.
* Restores the processor's architectural state from the provided context frame back into the hardware trap
* and exception frames.
*
* @param State
* Supplies a pointer to the processor state structure.
* @param TrapFrame
* Supplies a pointer to the trap frame that will receive the volatile processor state and control registers.
*
* @param ExceptionFrame
* Supplies a pointer to the exception frame that will receive the non-volatile integer and FP registers.
*
* @param ContextFrame
* Supplies a pointer to the context frame containing the state to be restored.
*
* @param ContextFlags
* Supplies a bitmask indicating which specific register groups should be restored from the ContextFrame.
*
* @return This routine does not return any value.
*
@@ -189,7 +217,223 @@ KE::Processor::RegisterProcessorBlock(ULONG CpuNumber,
*/
XTAPI
VOID
KE::Processor::SaveProcessorState(OUT PKPROCESSOR_STATE CpuState)
KE::Processor::RestoreProcessorContext(IN OUT PKTRAP_FRAME TrapFrame,
IN OUT PKEXCEPTION_FRAME ExceptionFrame,
IN PCONTEXT ContextFrame,
IN ULONG ContextFlags)
{
UNIMPLEMENTED;
}
/**
* Restores the processor's low-level hardware control state.
*
* @param CpuState
* Supplies a pointer to the processor state block containing the previously saved control data.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
KE::Processor::RestoreProcessorControlState(IN PKPROCESSOR_STATE CpuState)
{
/* Restore the CR registers */
AR::CpuFunctions::WriteControlRegister(0, CpuState->SpecialRegisters.Cr0);
AR::CpuFunctions::WriteControlRegister(2, CpuState->SpecialRegisters.Cr2);
AR::CpuFunctions::WriteControlRegister(3, CpuState->SpecialRegisters.Cr3);
AR::CpuFunctions::WriteControlRegister(4, CpuState->SpecialRegisters.Cr4);
AR::CpuFunctions::WriteControlRegister(8, CpuState->SpecialRegisters.Cr8);
/* Restore the DR registers */
AR::CpuFunctions::WriteDebugRegister(0, CpuState->SpecialRegisters.KernelDr0);
AR::CpuFunctions::WriteDebugRegister(1, CpuState->SpecialRegisters.KernelDr1);
AR::CpuFunctions::WriteDebugRegister(2, CpuState->SpecialRegisters.KernelDr2);
AR::CpuFunctions::WriteDebugRegister(3, CpuState->SpecialRegisters.KernelDr3);
AR::CpuFunctions::WriteDebugRegister(6, CpuState->SpecialRegisters.KernelDr6);
AR::CpuFunctions::WriteDebugRegister(7, CpuState->SpecialRegisters.KernelDr7);
/* Restore MSR registers */
AR::CpuFunctions::WriteModelSpecificRegister(X86_MSR_GSBASE, CpuState->SpecialRegisters.MsrGsBase);
AR::CpuFunctions::WriteModelSpecificRegister(X86_MSR_KERNEL_GSBASE, CpuState->SpecialRegisters.MsrGsSwap);
AR::CpuFunctions::WriteModelSpecificRegister(X86_MSR_CSTAR, CpuState->SpecialRegisters.MsrCStar);
AR::CpuFunctions::WriteModelSpecificRegister(X86_MSR_LSTAR, CpuState->SpecialRegisters.MsrLStar);
AR::CpuFunctions::WriteModelSpecificRegister(X86_MSR_STAR, CpuState->SpecialRegisters.MsrStar);
AR::CpuFunctions::WriteModelSpecificRegister(X86_MSR_FMASK, CpuState->SpecialRegisters.MsrSyscallMask);
/* Restore XMM control/status register */
AR::CpuFunctions::LoadMxcsrRegister(CpuState->SpecialRegisters.MxCsr);
/* Restore GDT, IDT and LDT */
AR::CpuFunctions::LoadGlobalDescriptorTable(&CpuState->SpecialRegisters.Gdtr.Limit);
AR::CpuFunctions::LoadInterruptDescriptorTable(&CpuState->SpecialRegisters.Idtr.Limit);
AR::CpuFunctions::LoadLocalDescriptorTable(CpuState->SpecialRegisters.Ldtr);
/* Force the TSS descriptor into a non-busy state and restore TaskRegister */
*(VOLATILE PUCHAR)((ULONG_PTR)CpuState->SpecialRegisters.Gdtr.Base + CpuState->SpecialRegisters.Tr + 5) &= ~0x02;
AR::CpuFunctions::LoadTaskRegister(CpuState->SpecialRegisters.Tr);
}
/**
* Restores the executing processor's state.
*
* @param TrapFrame
* Supplies a pointer to the hardware trap frame that will be populated with the restored volatile state.
*
* @param ExceptionFrame
* Supplies a pointer to the exception frame that will be populated with the restored non-volatile state.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
KE::Processor::RestoreProcessorState(OUT PKTRAP_FRAME TrapFrame,
OUT PKEXCEPTION_FRAME ExceptionFrame)
{
PKPROCESSOR_CONTROL_BLOCK Prcb;
/* Retrieve current processor control block */
Prcb = GetCurrentProcessorControlBlock();
/* Restore processor context */
RestoreProcessorContext(TrapFrame, ExceptionFrame, &Prcb->ProcessorState.ContextFrame, CONTEXT_ALL);
/* Restore processor control registers */
RestoreProcessorControlState(&Prcb->ProcessorState);
}
/**
* Constructs a standardized processor context from the hardware trap and exception frames.
*
* @param TrapFrame
* Supplies a pointer to the trap frame containing volatile processor state, control registers and debug
* registers saved at the time of the interrupt or exception.
*
* @param ExceptionFrame
* Supplies a pointer to the exception frame containing non-volatile integer and floating-point registers.
*
* @param ContextFrame
* Supplies a pointer to the context frame that will receive the processor state.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
KE::Processor::SaveProcessorContext(IN PKTRAP_FRAME TrapFrame,
IN PKEXCEPTION_FRAME ExceptionFrame,
IN OUT PCONTEXT ContextFrame)
{
/* Elevate RunLevel to APC_LEVEL to prevent thread preemption */
KE::RaiseRunLevel RunLevel(APC_LEVEL);
/* Check if control registers are requested */
if(ContextFrame->ContextFlags & CONTEXT_CONTROL)
{
/* Copy instruction pointer, stack pointer, and CPU status flags */
ContextFrame->Flags = TrapFrame->Flags;
ContextFrame->Rbp = TrapFrame->Rbp;
ContextFrame->Rip = TrapFrame->Rip;
ContextFrame->Rsp = TrapFrame->Rsp;
ContextFrame->SegCs = TrapFrame->SegCs;
ContextFrame->SegSs = TrapFrame->SegSs;
}
/* Check if general-purpose integer registers are requested */
if(ContextFrame->ContextFlags & CONTEXT_INTEGER)
{
/* Copy volatile integer registers directly from the trap frame */
ContextFrame->Rax = TrapFrame->Rax;
ContextFrame->Rcx = TrapFrame->Rcx;
ContextFrame->Rdx = TrapFrame->Rdx;
ContextFrame->R8 = TrapFrame->R8;
ContextFrame->R9 = TrapFrame->R9;
ContextFrame->R10 = TrapFrame->R10;
ContextFrame->R11 = TrapFrame->R11;
/* Check if a valid exception frame was provided */
if(ExceptionFrame)
{
/* Copy non-volatile integer registers from the exception frame */
ContextFrame->Rbx = ExceptionFrame->Rbx;
ContextFrame->R12 = ExceptionFrame->R12;
ContextFrame->R13 = ExceptionFrame->R13;
ContextFrame->R14 = ExceptionFrame->R14;
ContextFrame->R15 = ExceptionFrame->R15;
ContextFrame->Rdi = ExceptionFrame->Rdi;
ContextFrame->Rsi = ExceptionFrame->Rsi;
}
}
/* Check if segment registers are requested */
if(ContextFrame->ContextFlags & CONTEXT_SEGMENTS)
{
/* Populate segment selectors with standard Ring 3 values */
ContextFrame->SegDs = KGDT_R3_DATA | RPL_MASK;
ContextFrame->SegEs = KGDT_R3_DATA | RPL_MASK;
ContextFrame->SegFs = KGDT_R3_CMTEB | RPL_MASK;
ContextFrame->SegGs = KGDT_R3_DATA | RPL_MASK;
}
/* Check if floating-point registers are requested */
if(ContextFrame->ContextFlags & CONTEXT_FLOATING_POINT)
{
/* Copy the SSE control/status register and volatile XMM registers */
ContextFrame->MxCsr = TrapFrame->MxCsr;
ContextFrame->Xmm0 = TrapFrame->Xmm0;
ContextFrame->Xmm1 = TrapFrame->Xmm1;
ContextFrame->Xmm2 = TrapFrame->Xmm2;
ContextFrame->Xmm3 = TrapFrame->Xmm3;
ContextFrame->Xmm4 = TrapFrame->Xmm4;
ContextFrame->Xmm5 = TrapFrame->Xmm5;
/* Check if a valid exception frame was provided */
if(ExceptionFrame)
{
/* Copy non-volatile XMM registers from the exception frame */
ContextFrame->Xmm6 = ExceptionFrame->Xmm6;
ContextFrame->Xmm7 = ExceptionFrame->Xmm7;
ContextFrame->Xmm8 = ExceptionFrame->Xmm8;
ContextFrame->Xmm9 = ExceptionFrame->Xmm9;
ContextFrame->Xmm10 = ExceptionFrame->Xmm10;
ContextFrame->Xmm11 = ExceptionFrame->Xmm11;
ContextFrame->Xmm12 = ExceptionFrame->Xmm12;
ContextFrame->Xmm13 = ExceptionFrame->Xmm13;
ContextFrame->Xmm14 = ExceptionFrame->Xmm14;
ContextFrame->Xmm15 = ExceptionFrame->Xmm15;
}
}
/* Check if debug registers are requested */
if(ContextFrame->ContextFlags & CONTEXT_DEBUG_REGISTERS)
{
/* Copy debug registers */
ContextFrame->Dr0 = TrapFrame->Dr0;
ContextFrame->Dr1 = TrapFrame->Dr1;
ContextFrame->Dr2 = TrapFrame->Dr2;
ContextFrame->Dr3 = TrapFrame->Dr3;
ContextFrame->Dr6 = TrapFrame->Dr6;
ContextFrame->Dr7 = TrapFrame->Dr7;
}
}
/**
* Saves the current processor's low-level hardware control state.
*
* @param State
* Supplies a pointer to the processor state block that will receive processor's control data.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
KE::Processor::SaveProcessorControlState(OUT PKPROCESSOR_STATE CpuState)
{
/* Save CR registers */
CpuState->SpecialRegisters.Cr0 = AR::CpuFunctions::ReadControlRegister(0);
@@ -223,3 +467,36 @@ KE::Processor::SaveProcessorState(OUT PKPROCESSOR_STATE CpuState)
AR::CpuFunctions::StoreLocalDescriptorTable(&CpuState->SpecialRegisters.Ldtr);
AR::CpuFunctions::StoreTaskRegister(&CpuState->SpecialRegisters.Tr);
}
/**
* Captures the executing processor's state.
*
* @param TrapFrame
* Supplies a pointer to the hardware trap frame containing the processor's volatile state.
*
* @param ExceptionFrame
* Supplies a pointer to the exception frame containing the processor's non-volatile state.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
KE::Processor::SaveProcessorState(IN PKTRAP_FRAME TrapFrame,
IN PKEXCEPTION_FRAME ExceptionFrame)
{
PKPROCESSOR_CONTROL_BLOCK Prcb;
/* Retrieve current processor control block */
Prcb = GetCurrentProcessorControlBlock();
/* Set context flags to save whole all context */
Prcb->ProcessorState.ContextFrame.ContextFlags = CONTEXT_ALL;
/* Save processor context */
SaveProcessorContext(TrapFrame, ExceptionFrame, &Prcb->ProcessorState.ContextFrame);
/* Save processor control registers */
SaveProcessorControlState(&Prcb->ProcessorState);
}

View File

@@ -4,11 +4,234 @@
* FILE: xtoskrnl/ke/panic.cc
* DESCRIPTION: System shutdown and kernel panic mechanism
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
* Aiken Harris <harraiken91@gmail.com>
*/
#include <xtos.hh>
/**
* Freezes the execution of the current processor during a fatal system crash or an interactive debugging session.
*
* @param TrapFrame
* Supplies an optional pointer to the trap frame captured at the moment the IPI_FREEZE was delivered.
*
* @param ExceptionFrame
* Supplies an optional pointer to the exception frame containing the non-volatile processor state.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
KE::Crash::FreezeCurrentExecution(IN PKTRAP_FRAME TrapFrame,
IN PKEXCEPTION_FRAME ExceptionFrame)
{
KCONTINUE_STATUS ContinueStatus;
PKPROCESSOR_CONTROL_BLOCK Prcb;
BOOLEAN Interrupts;
/* Check whether interrupts are enabled */
Interrupts = AR::CpuFunctions::InterruptsEnabled();
/* Disable interrupts */
AR::CpuFunctions::ClearInterruptFlag();
/* Start a guarded code block */
{
/* Raise runlevel to HIGH level */
KE::RaiseRunLevel RunLevel(HIGH_LEVEL);
/* Get the processor control block */
Prcb = KE::Processor::GetCurrentProcessorControlBlock();
/* Verify that this core was genuinely requested to freeze */
if(Prcb->IpiFrozen != IPI_FROZEN_STATE_FREEZE)
{
/* Spurious call or already thawed, return */
return;
}
/* Acknowledge the freeze request to the initiator */
Prcb->IpiFrozen = IPI_FROZEN_STATE_FROZEN;
/* Check if there is a valid trap frame to save the context */
if(TrapFrame != NULLPTR)
{
/* Capture the processor state */
KE::Processor::SaveProcessorState(TrapFrame, ExceptionFrame);
}
/* Enter the stateless polling loop */
while(Prcb->IpiFrozen != IPI_FROZEN_STATE_THAW)
{
/* Check for debugger processor switch */
if(Prcb->IpiFrozen & IPI_FROZEN_STATE_ACTIVE)
{
/* Let the CPU enter the debugger as the active processor */
ContinueStatus = KD::Debugger::SwitchProcessor();
/* Set the state back to passively frozen */
Prcb->IpiFrozen = IPI_FROZEN_STATE_FROZEN;
/* Check if the status is ContinueSuccess */
if(ContinueStatus == ContinueSuccess)
{
/* Release the freeze owner to globally resume system execution */
FreezeOwner->IpiFrozen = IPI_FROZEN_STATE_THAW;
}
}
/* Mitigate spin-lock starvation and enforce memory coherence */
AR::CpuFunctions::YieldProcessor();
AR::CpuFunctions::MemoryBarrier();
}
/* Thaw signal received, check if there is a need to restore context */
if(TrapFrame != NULLPTR)
{
/* Restore the processor state */
KE::Processor::RestoreProcessorState(TrapFrame, ExceptionFrame);
}
/* Acknowledge the thaw and mark the processor as fully operational */
Prcb->IpiFrozen = IPI_FROZEN_STATE_RUNNING;
/* Flush the Translation Lookaside Buffer (TLB) */
AR::CpuFunctions::FlushTlb();
}
/* Check whether interrupts need to be re-enabled */
if(Interrupts)
{
/* Re-enable interrupts */
AR::CpuFunctions::SetInterruptFlag();
}
}
/**
* Asserts control over the entire system by freezing all other executing processors.
*
* @param TrapFrame
* Supplies a pointer to the trap frame of the initiating processor.
*
* @param ExceptionFrame
* Supplies a pointer to the exception frame of the initiating processor.
*
* @return This routine returns the interrupt state prior to the freeze execution.
*
* @since XT 1.0
*/
XTAPI
BOOLEAN
KE::Crash::FreezeExecution(IN PKTRAP_FRAME TrapFrame,
IN PKEXCEPTION_FRAME ExceptionFrame)
{
PKPROCESSOR_BLOCK ProcessorBlock;
PKPROCESSOR_CONTROL_BLOCK Prcb;
KRUNLEVEL OldRunLevel;
ULONG CpuCount, Index;
BOOLEAN Interrupts;
/* Check whether interrupts are enabled */
Interrupts = AR::CpuFunctions::InterruptsEnabled();
/* Disable interrupts */
AR::CpuFunctions::ClearInterruptFlag();
/* Raise runlevel to HIGH level */
OldRunLevel = KE::RunLevel::RaiseRunLevel(HIGH_LEVEL);
/* Get processor control block for the executing core */
Prcb = KE::Processor::GetCurrentProcessorControlBlock();
/* Check if CPU already owns the freeze */
if(FreezeOwner == Prcb && Prcb->IpiFrozen == IPI_FROZEN_STATE_OWNER)
{
/* Freeze already owned, return interrupt state */
return Interrupts;
}
/* Attempt to establish ownership of the freeze */
while(RTL::Atomic::CompareExchangePointer((PVOID*)&FreezeOwner, NULLPTR, Prcb))
{
/* Freeze owned by another processor, spin until the lock is released */
while(FreezeOwner != NULLPTR)
{
/* Check whether interrupts need to be re-enabled */
if(Interrupts)
{
/* Re-enable interrupts */
AR::CpuFunctions::SetInterruptFlag();
}
/* Process pending IPIs */
KE::Ipi::HandleIpiService(TrapFrame, ExceptionFrame);
/* Disable interrupts */
AR::CpuFunctions::ClearInterruptFlag();
}
}
/* Re-fetch the processor control block */
Prcb = KE::Processor::GetCurrentProcessorControlBlock();
/* Set the freeze state */
Prcb->IpiFrozen = IPI_FROZEN_STATE_OWNER | IPI_FROZEN_STATE_ACTIVE;
/* Get the number of installed CPUs */
CpuCount = KE::Processor::GetInstalledCpus();
/* Iterate over all installed CPUs */
for(Index = 0; Index < CpuCount; Index++)
{
/* Get the processor block for next CPU */
ProcessorBlock = KE::Processor::GetProcessorBlock(Index);
/* Check if the processor block exists and the processor is running */
if(ProcessorBlock != NULLPTR && ProcessorBlock->Started)
{
/* Do not freeze ourselves */
if(ProcessorBlock->Prcb.CpuNumber != Prcb->CpuNumber)
{
/* Request the target processor to freeze execution */
ProcessorBlock->Prcb.IpiFrozen = IPI_FROZEN_STATE_FREEZE;
}
}
}
/* Broadcast the freeze request to all other processors */
KE::Ipi::SendBroadcastIpi(IPI_FREEZE, FALSE);
/* Iterate over all installed CPUs to verify their frozen state */
for(Index = 0; Index < CpuCount; Index++)
{
/* Get the processor block for next CPU */
ProcessorBlock = KE::Processor::GetProcessorBlock(Index);
/* Check if the processor block exists and the processor is running */
if(ProcessorBlock != NULLPTR && ProcessorBlock->Started)
{
/* Do not wait for ourselves */
if(ProcessorBlock->Prcb.CpuNumber != Prcb->CpuNumber)
{
/* Wait for the target processor to acknowledge the freeze */
while(ProcessorBlock->Prcb.IpiFrozen != IPI_FROZEN_STATE_FROZEN)
{
/* Mitigate spin-lock starvation */
AR::CpuFunctions::YieldProcessor();
AR::CpuFunctions::MemoryBarrier();
}
}
}
}
/* Save original runlevel and return the original interrupt state */
RunLevel = OldRunLevel;
return Interrupts;
}
/**
* Halts the system.
*
@@ -43,6 +266,7 @@ XTAPI
VOID
KE::Crash::Panic(IN ULONG Code)
{
/* Call panic function */
Panic(Code, 0, 0, 0, 0);
}
@@ -76,7 +300,115 @@ KE::Crash::Panic(IN ULONG Code,
IN ULONG_PTR Parameter3,
IN ULONG_PTR Parameter4)
{
/* Set kernel panic state */
KernelPanic = TRUE;
/* Broadcast IPI_FREEZE to all other processors */
FreezeExecution(NULLPTR, NULLPTR);
/* Print error message to debug console */
KD::DebugIo::KdPrint(L"Fatal System Error: 0x%08lx (0x%zx 0x%zx 0x%zx 0x%zx)\nKernel Panic!\n\n",
Code, Parameter1, Parameter2, Parameter3, Parameter4);
/* Halt system */
HaltSystem();
}
/**
* Determines whether the system has experienced a fatal error and entered a kernel panic state.
*
* @return This routine returns TRUE if the system has halted due to a kernel panic, or FALSE otherwise.
*
* @since XT 1.0
*/
XTAPI
BOOLEAN
KE::Crash::SystemCrashed(VOID)
{
/* Return kernel panic state */
return KernelPanic;
}
/**
* Resumes execution of the entire system following a system freeze or an interactive debugging session.
*
* @param Interrupts
* Supplies the original interrupt state captured prior to the freeze.
* This determines if local interrupts should be re-enabled.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
KE::Crash::ThawExecution(IN BOOLEAN Interrupts)
{
PKPROCESSOR_BLOCK ProcessorBlock;
PKPROCESSOR_CONTROL_BLOCK Prcb;
ULONG CpuCount, Index;
/* Get the processor control block and available CPU count */
Prcb = KE::Processor::GetCurrentProcessorControlBlock();
CpuCount = KE::Processor::GetInstalledCpus();
/* Mark the freeze owner processor as running */
Prcb->IpiFrozen = IPI_FROZEN_STATE_RUNNING;
/* Iterate over all CPUs to signal them to thaw */
for(Index = 0; Index < CpuCount; Index++)
{
/* Get the processor block for the next CPU */
ProcessorBlock = KE::Processor::GetProcessorBlock(Index);
/* Check if the processor block exists and the processor is running */
if(ProcessorBlock != NULLPTR && ProcessorBlock->Started)
{
/* Do not thaw ourselves */
if(ProcessorBlock->Prcb.CpuNumber != Prcb->CpuNumber)
{
/* Request the target processor to thaw execution */
ProcessorBlock->Prcb.IpiFrozen = IPI_FROZEN_STATE_THAW;
}
}
}
/* Iterate over all installed CPUs to verify they have resumed */
for(Index = 0; Index < CpuCount; Index++)
{
/* Get the processor block for the next CPU */
ProcessorBlock = KE::Processor::GetProcessorBlock(Index);
/* Check if the processor block exists and the processor is running */
if(ProcessorBlock != NULLPTR && ProcessorBlock->Started)
{
/* Do not wait for ourselves */
if(ProcessorBlock->Prcb.CpuNumber != Prcb->CpuNumber)
{
/* Wait for the target processor to acknowledge it is running */
while(ProcessorBlock->Prcb.IpiFrozen != IPI_FROZEN_STATE_RUNNING)
{
/* Mitigate spin-lock starvation */
AR::CpuFunctions::YieldProcessor();
AR::CpuFunctions::MemoryBarrier();
}
}
}
}
/* Release the global freeze owner lock */
RTL::Atomic::ExchangePointer((PVOID *)&FreezeOwner, NULLPTR);
/* Flush the Translation Lookaside Buffer (TLB) */
AR::CpuFunctions::FlushTlb();
/* Restore the original runlevel from before the freeze */
KE::RunLevel::LowerRunLevel(RunLevel);
/* Check whether interrupts need to be re-enabled */
if(Interrupts)
{
/* Re-enable interrupts */
AR::CpuFunctions::SetInterruptFlag();
}
}

View File

@@ -12,6 +12,15 @@
/* Kernel initialization block passed by boot loader */
PKERNEL_INITIALIZATION_BLOCK KE::BootInformation::InitializationBlock = {};
/* Processor control block belonging to the freeze owner */
PKPROCESSOR_CONTROL_BLOCK KE::Crash::FreezeOwner;
/* Kernel panic state */
BOOLEAN KE::Crash::KernelPanic;
/* System runlevel before execution freeze */
KRUNLEVEL KE::Crash::RunLevel;
/* Kernel initial process */
EPROCESS KE::KProcess::InitialProcess;
@@ -95,3 +104,6 @@ LONG KE::SystemTime::TickOffset;
/* The runtime adjustment value applied to the system clock at each interrupt */
ULONG KE::SystemTime::TimeAdjustment;
/* Kernel timer table containing a list of active timers */
LIST_ENTRY KE::Timer::TimerTableListHead[KTIMER_TABLE_SIZE];

View File

@@ -4,11 +4,82 @@
* FILE: xtoskrnl/ke/dispatch.cc
* DESCRIPTION: Kernel Thread Dispatcher
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
* Aiken Harris <harraiken91@gmail.com>
*/
#include <xtos.hh>
/**
* Enters the system idle thread loop for the current processor, running continuously when no other
* threads are scheduled for execution.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
KE::Dispatcher::EnterIdleLoop(VOID)
{
PKTHREAD CurrentThread, NextThread;
PKPROCESSOR_CONTROL_BLOCK Prcb;
/* Retrieve the processor control block */
Prcb = KE::Processor::GetCurrentProcessorControlBlock();
/* Enter the infinite idle loop */
while(TRUE)
{
/* Temporarily enable interrupts and yield the processor to handle pending hardware events */
AR::CpuFunctions::SetInterruptFlag();
AR::CpuFunctions::YieldProcessor();
AR::CpuFunctions::YieldProcessor();
AR::CpuFunctions::ClearInterruptFlag();
/* Check for pending deferred ready threads, DPCs, or timer requests */
if(Prcb->DeferredReadyListHead.Next ||
Prcb->DpcData[0].DpcQueueDepth ||
Prcb->TimerRequest)
{
/* Unimplemented path */
UNIMPLEMENTED;
}
/* Check if a new thread has been scheduled for execution */
if(Prcb->NextThread)
{
/* Enable interrupts to allow hardware events during context switch preparation */
AR::CpuFunctions::SetInterruptFlag();
/* Capture the current and next thread pointers */
CurrentThread = Prcb->CurrentThread;
NextThread = Prcb->NextThread;
/* Update the processor control block with the incoming thread */
Prcb->NextThread = NULLPTR;
Prcb->CurrentThread = NextThread;
/* Transition the incoming thread to the running state */
NextThread->State = Running;
/* Start a guarded code block */
{
/* Raise runlevel to SYNC level */
KE::RaiseRunLevel RunLevel(SYNC_LEVEL);
/* Perform the context switch away from the idle thread */
KE::Dispatcher::SwitchContext(CurrentThread, APC_LEVEL);
}
}
else
{
/* No threads scheduled, enter a low-power processor state and wait for interrupts */
Prcb->PowerState.IdleFunction(&Prcb->PowerState);
}
}
}
/**
* Exits the dispatcher, switches context to a new thread and lowers runlevel to its original state.
*
@@ -29,6 +100,25 @@ KE::Dispatcher::ExitDispatcher(IN KRUNLEVEL OldRunLevel)
RunLevel::LowerRunLevel(OldRunLevel);
}
/**
* Handles the dispatch interrupt by retiring pending DPCs, asking the scheduler for the next runnable thread
* and performing the context switch.
*
* @param TrapFrame
* Supplies a pointer to the hardware trap frame representing the interrupted context.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTCDECL
VOID
KE::Dispatcher::HandleDispatchInterrupt(IN PKTRAP_FRAME TrapFrame)
{
/* End the interrupt */
HL::Pic::SendEoi();
}
/**
* Updates the runtime quantum of the currently executing thread and handles preemption.
*
@@ -47,4 +137,101 @@ VOID
KE::Dispatcher::UpdateRunTime(IN PKTRAP_FRAME TrapFrame,
IN KRUNLEVEL RunLevel)
{
PKPROCESSOR_CONTROL_BLOCK ControlBlock;
PKTHREAD Thread;
/* Retrieve current processor control block and current thread */
ControlBlock = KE::Processor::GetCurrentProcessorControlBlock();
Thread = KE::Processor::GetCurrentThread();
/* Increment interrupt count */
ControlBlock->InterruptCount++;
/* Check if the thread ran in user mode */
if(TrapFrame->PreviousMode == UserMode)
{
/* Atomically increment the process-wide user time */
RTL::Atomic::Increment32((PLONG)&Thread->ApcState.Process->UserTime);
/* Increment thread and total time this processor has spent executing in user time */
ControlBlock->UserTime++;
Thread->UserTime++;
}
else
{
/* Increment the total time this processor has spent executing in kernel mode */
ControlBlock->KernelTime++;
/* Check if normal kernel thread execution was interrupted */
if((RunLevel < DISPATCH_LEVEL) || !(ControlBlock->DpcRoutineActive))
{
/* Atomically increment the process-wide kernel time */
RTL::Atomic::Increment32((PLONG)&Thread->ApcState.Process->KernelTime);
/* Increment the kernel execution time for the current thread */
Thread->KernelTime++;
}
else if(RunLevel > DISPATCH_LEVEL)
{
/* Increment the time spent servicing hardware interrupts */
ControlBlock->InterruptTime++;
}
else
{
/* Increment the time spent servicing DPCs */
ControlBlock->DpcTime++;
}
}
/* Calculate the new DPC request rate as a moving average of the current and previous rates */
ControlBlock->DpcRequestRate = ((ControlBlock->DpcData[0].DpcCount - ControlBlock->DpcLastCount) +
ControlBlock->DpcRequestRate) >> 1;
/* Snapshot the current DPC count */
ControlBlock->DpcLastCount = ControlBlock->DpcData[0].DpcCount;
/* Check if there are pending DPCs, no DPC routine is currently executing, and DPC interrupt is not pending */
if((ControlBlock->DpcData[0].DpcQueueDepth) &&
!(ControlBlock->DpcRoutineActive) &&
!(ControlBlock->DpcInterruptRequested))
{
/* Reset the adjustment threshold counter */
ControlBlock->AdjustDpcThreshold = DPC_ADJUST_THRESHOLD;
/* Request a DISPATCH_LEVEL software interrupt to process the pending DPCs */
HL::Irq::SendSoftwareInterrupt(DISPATCH_LEVEL);
/* Evaluate if the DPC request rate is below the ideal threshold */
if((ControlBlock->DpcRequestRate < DPC_IDEAL_RATE) && (ControlBlock->MaximumDpcQueueDepth > 1))
{
/* Decrease the maximum queue depth */
ControlBlock->MaximumDpcQueueDepth--;
}
}
else
{
/* Decrement the tuning threshold counter and verify if an adjustment cycle is required */
if(!(--ControlBlock->AdjustDpcThreshold))
{
/* Reset the counter for the next tuning cycle */
ControlBlock->AdjustDpcThreshold = DPC_ADJUST_THRESHOLD;
/* Check if the current queue depth limit is below the system-wide absolute maximum */
if(ControlBlock->MaximumDpcQueueDepth != DPC_MAXIMUM_QUEUE_DEPTH)
{
/* Increase the maximum queue depth to batch more DPCs */
ControlBlock->MaximumDpcQueueDepth++;
}
}
}
/* Decrement the execution time slice */
Thread->Quantum -= CLOCK_QUANTUM_DECREMENT;
/* Check if the thread has exhausted its quantum, ignoring the idle thread */
if((Thread->Quantum <= 0) && (Thread != ControlBlock->IdleThread))
{
/* Request a DISPATCH_LEVEL software interrupt to preempt the thread */
HL::Irq::SendSoftwareInterrupt(DISPATCH_LEVEL);
}
}

View File

@@ -22,13 +22,12 @@
*
* @since XT 1.0
*/
XTASSEMBLY
XTFASTCALL
BOOLEAN
KE::Dispatcher::SwitchContext(IN PKTHREAD CurrentThread,
IN KRUNLEVEL RunLevel)
{
BOOLEAN PendingApc;
/* Save registers to the exception frame and invoke the stack switch routine */
__asm__ volatile("subl %[ExFrameSize], %%esp\n"
"movl %%esi, %c[ExEsi](%%esp)\n"
@@ -41,19 +40,15 @@ KE::Dispatcher::SwitchContext(IN PKTHREAD CurrentThread,
"movl %c[ExEdi](%%esp), %%edi\n"
"movl %c[ExEsi](%%esp), %%esi\n"
"addl %[ExFrameSize], %%esp\n"
: "=a" (PendingApc)
: "c" (CurrentThread),
"d" (RunLevel),
[ExFrameSize] "i" (sizeof(KEXCEPTION_FRAME) - 4),
"ret\n"
:
: [ExFrameSize] "i" (sizeof(KEXCEPTION_FRAME) - 4),
[ExEbp] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Ebp)),
[ExEbx] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Ebx)),
[ExEdi] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Edi)),
[ExEsi] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Esi)),
[SwitchRoutine] "i" (SwitchThreadStack)
: "cc", "memory");
/* Return the APC status */
return PendingApc;
}
/**
@@ -92,13 +87,12 @@ KE::Dispatcher::SwitchThreadContext(IN PKTHREAD CurrentThread,
*
* @since XT 1.0
*/
XTASSEMBLY
XTFASTCALL
BOOLEAN
KE::Dispatcher::SwitchThreadStack(IN PKTHREAD CurrentThread,
IN KRUNLEVEL RunLevel)
{
BOOLEAN PendingApc;
/* Save old state, synchronize with CPUs, switch stack and call the switch routine */
__asm__ volatile("subl %[FrameSize], %%esp\n"
"movl %%fs:%c[PrcbcCurrentThread], %%ebx\n"
@@ -116,10 +110,9 @@ KE::Dispatcher::SwitchThreadStack(IN PKTHREAD CurrentThread,
"movzbl %c[SwApcBypass](%%esp), %%edx\n"
"call %P[SwitchRoutine]\n"
"addl %[FrameSize], %%esp\n"
: "=a" (PendingApc)
: "c" (CurrentThread),
"d" (RunLevel),
[FrameSize] "i" (sizeof(KSWITCH_FRAME) - 4),
"ret\n"
:
: [FrameSize] "i" (sizeof(KSWITCH_FRAME) - 4),
[PrcbcCurrentThread] "i" (FIELD_OFFSET(KPROCESSOR_BLOCK, Prcb.CurrentThread)),
[SwApcBypass] "i" (FIELD_OFFSET(KSWITCH_FRAME, ApcBypassDisabled)),
[SwExceptionList] "i" (FIELD_OFFSET(KSWITCH_FRAME, ExceptionList)),
@@ -128,7 +121,4 @@ KE::Dispatcher::SwitchThreadStack(IN PKTHREAD CurrentThread,
[ThrdStack] "i" (FIELD_OFFSET(KTHREAD, KernelStack)),
[ThrdSwapBusy] "i" (FIELD_OFFSET(KTHREAD, SwapBusy))
: "cc", "memory");
/* Return the APC status */
return PendingApc;
}

View File

@@ -46,21 +46,30 @@ KE::KernelInit::BootstrapApplicationProcessor(IN PPROCESSOR_START_BLOCK StartBlo
PO::Idle::InitializeProcessorIdleState(ControlBlock);
/* Save processor state */
KE::Processor::SaveProcessorState(&ControlBlock->ProcessorState);
KE::Processor::SaveProcessorControlState(&ControlBlock->ProcessorState);
/* Initialize per-CPU spin lock queues */
KE::SpinLock::InitializeLockQueues();
/* Initialize interrupt handlers */
InitializeInterruptHandlers();
/* Lower to APC runlevel */
KE::RunLevel::LowerRunLevel(APC_LEVEL);
/* Initialize local clock for this CPU */
HL::Timer::InitializeLocalClock();
/* Enter infinite loop */
DebugPrint(L"KernelInit::BootstrapApplicationProcessor() finished for CPU #%lu. Entering infinite loop.\n",
/* Create and initialize IDLE thread */
PS::Thread::CreateIdleThread(ControlBlock, StartBlock->Stack);
/* Register DISPATCH interrupt handler */
HL::Irq::RegisterSystemInterruptHandler(APIC_VECTOR_DPC, KE::Dispatcher::HandleDispatchInterrupt);
/* Enter idle loop */
DebugPrint(L"KernelInit::BootstrapApplicationProcessor() finished for CPU #%lu. Entering IDLE loop.\n",
ControlBlock->CpuNumber);
KE::Crash::HaltSystem();
KE::Dispatcher::EnterIdleLoop();
}
/**
@@ -76,62 +85,65 @@ VOID
KE::KernelInit::BootstrapKernel(VOID)
{
PKPROCESSOR_CONTROL_BLOCK Prcb;
ULONG_PTR PageDirectory[2];
PKPROCESS CurrentProcess;
PKTHREAD CurrentThread;
/* Get processor control block and current thread */
/* Get processor control block */
Prcb = KE::Processor::GetCurrentProcessorControlBlock();
CurrentThread = KE::Processor::GetCurrentThread();
/* Get current process */
CurrentProcess = CurrentThread->ApcState.Process;
/* Initialize CPU power state structures */
PO::Idle::InitializeProcessorIdleState(Prcb);
/* Save processor state */
KE::Processor::SaveProcessorState(&Prcb->ProcessorState);
KE::Processor::SaveProcessorControlState(&Prcb->ProcessorState);
/* Initialize spin locks */
KE::SpinLock::InitializeAllLocks();
KE::SpinLock::InitializeLockQueues();
/* Initialize interrupt handlers */
InitializeInterruptHandlers();
/* Lower to APC runlevel */
KE::RunLevel::LowerRunLevel(APC_LEVEL);
/* Initialize XTOS kernel */
InitializeKernel();
/* Initialize Idle process */
PageDirectory[0] = 0;
PageDirectory[1] = 0;
KE::KProcess::InitializeProcess(CurrentProcess, 0, MAXULONG_PTR, PageDirectory, FALSE);
CurrentProcess->Quantum = MAXCHAR;
/* Initialize Idle thread */
KE::KThread::InitializeThread(CurrentProcess, CurrentThread, NULLPTR, NULLPTR, NULLPTR,
NULLPTR, NULLPTR, AR::ProcessorSupport::GetBootStack(), TRUE);
CurrentThread->NextProcessor = Prcb->CpuNumber;
CurrentThread->Priority = THREAD_HIGH_PRIORITY;
CurrentThread->State = Running;
CurrentThread->Affinity = (ULONG_PTR)1 << Prcb->CpuNumber;
CurrentThread->WaitRunLevel = DISPATCH_LEVEL;
CurrentProcess->ActiveProcessors |= (ULONG_PTR)1 << Prcb->CpuNumber;
/* Initialize Memory Manager */
MM::Manager::InitializeMemoryManager();
/* Enable shadow buffer for framebuffer */
HL::FrameBuffer::EnableShadowBuffer();
/* Create and initialize IDLE process */
PS::Process::CreateIdleProcess(Prcb);
/* Start all application processors */
KE::Processor::InitializeProcessorBlocks();
HL::Cpu::InitializeProcessorAffinity();
HL::Cpu::StartAllProcessors();
/* Enter infinite loop */
DebugPrint(L"KernelInit::BootstrapKernel() finished. Entering infinite loop.\n");
KE::Crash::HaltSystem();
/* Register DISPATCH interrupt handler */
HL::Irq::RegisterSystemInterruptHandler(APIC_VECTOR_DPC, KE::Dispatcher::HandleDispatchInterrupt);
/* Enter idle loop */
DebugPrint(L"KernelInit::BootstrapKernel() finished. Entering IDLE loop.\n");
KE::Dispatcher::EnterIdleLoop();
}
/**
* Initializes and registers the core system interrupt handlers.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
KE::KernelInit::InitializeInterruptHandlers(VOID)
{
/* Register interrupt handlers */
HL::Irq::RegisterSystemInterruptHandler(APIC_VECTOR_DPC, KE::Dispatcher::HandleDispatchInterrupt);
HL::Irq::RegisterSystemInterruptHandler(APIC_VECTOR_IPI, KE::Ipi::HandleIpiInterrupt);
}
/**

View File

@@ -66,7 +66,7 @@ KE::KThread::InitializeThreadContext(IN PKTHREAD Thread,
/* Disable coprocessor floating point state */
Thread->NpxState = NPX_STATE_UNLOADED;
Thread->Header.NpxIrql = PASSIVE_LEVEL;
Thread->NpxRunLevel = PASSIVE_LEVEL;
/* Set initial floating point state */
FxSaveFormat = (PFX_SAVE_FORMAT)ContextRecord->ExtendedRegisters;

View File

@@ -66,6 +66,21 @@ KE::Processor::GetCurrentThread(VOID)
return (PKTHREAD)AR::CpuFunctions::ReadFSDualWord(FIELD_OFFSET(KPROCESSOR_BLOCK, Prcb.CurrentThread));
}
/**
* Retrieves the number of installed and enabled CPUs in the system.
*
* @return This routine returns the number of installed CPUs in the system.
*
* @since XT 1.0
*/
XTAPI
ULONG
KE::Processor::GetInstalledCpus(VOID)
{
/* Return number of installed CPUs */
return InstalledCpus;
}
/**
* Gets the processor block for the specified processor number.
*
@@ -122,6 +137,9 @@ KE::Processor::InitializeProcessorBlocks()
/* Zero the array initially */
RTL::Memory::ZeroMemory(ProcessorBlocks, InstalledCpus * sizeof(PKPROCESSOR_BLOCK));
/* Register the processor block for the BSP processor */
KE::Processor::RegisterProcessorBlock(0, KE::Processor::GetCurrentProcessorBlock());
/* Return success */
return STATUS_SUCCESS;
}
@@ -178,10 +196,20 @@ KE::Processor::RegisterProcessorBlock(ULONG CpuNumber,
}
/**
* Saves the current processor state.
* Restores the processor's architectural state from the provided context frame back into the hardware trap
* and exception frames.
*
* @param State
* Supplies a pointer to the processor state structure.
* @param TrapFrame
* Supplies a pointer to the trap frame that will receive the volatile processor state and control registers.
*
* @param ExceptionFrame
* Supplies a pointer to the exception frame that will receive the non-volatile integer and FP registers.
*
* @param ContextFrame
* Supplies a pointer to the context frame containing the state to be restored.
*
* @param ContextFlags
* Supplies a bitmask indicating which specific register groups should be restored from the ContextFrame.
*
* @return This routine does not return any value.
*
@@ -189,7 +217,183 @@ KE::Processor::RegisterProcessorBlock(ULONG CpuNumber,
*/
XTAPI
VOID
KE::Processor::SaveProcessorState(OUT PKPROCESSOR_STATE CpuState)
KE::Processor::RestoreProcessorContext(IN OUT PKTRAP_FRAME TrapFrame,
IN OUT PKEXCEPTION_FRAME ExceptionFrame,
IN PCONTEXT ContextFrame,
IN ULONG ContextFlags)
{
UNIMPLEMENTED;
}
/**
* Restores the processor's low-level hardware control state.
*
* @param CpuState
* Supplies a pointer to the processor state block containing the previously saved control data.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
KE::Processor::RestoreProcessorControlState(IN PKPROCESSOR_STATE CpuState)
{
/* Restore CR registers */
AR::CpuFunctions::WriteControlRegister(0, CpuState->SpecialRegisters.Cr0);
AR::CpuFunctions::WriteControlRegister(2, CpuState->SpecialRegisters.Cr2);
AR::CpuFunctions::WriteControlRegister(3, CpuState->SpecialRegisters.Cr3);
AR::CpuFunctions::WriteControlRegister(4, CpuState->SpecialRegisters.Cr4);
/* Restore DR registers */
AR::CpuFunctions::WriteDebugRegister(0, CpuState->SpecialRegisters.KernelDr0);
AR::CpuFunctions::WriteDebugRegister(1, CpuState->SpecialRegisters.KernelDr1);
AR::CpuFunctions::WriteDebugRegister(2, CpuState->SpecialRegisters.KernelDr2);
AR::CpuFunctions::WriteDebugRegister(3, CpuState->SpecialRegisters.KernelDr3);
AR::CpuFunctions::WriteDebugRegister(6, CpuState->SpecialRegisters.KernelDr6);
AR::CpuFunctions::WriteDebugRegister(7, CpuState->SpecialRegisters.KernelDr7);
/* Restore GDT, IDT and LDT */
AR::CpuFunctions::LoadGlobalDescriptorTable(&CpuState->SpecialRegisters.Gdtr.Limit);
AR::CpuFunctions::LoadInterruptDescriptorTable(&CpuState->SpecialRegisters.Idtr.Limit);
AR::CpuFunctions::LoadLocalDescriptorTable(CpuState->SpecialRegisters.Ldtr);
/* Force the TSS descriptor into a non-busy state and restore TaskRegister */
*(VOLATILE PUCHAR)((ULONG_PTR)CpuState->SpecialRegisters.Gdtr.Base + CpuState->SpecialRegisters.Tr + 5) &= ~0x02;
AR::CpuFunctions::LoadTaskRegister(CpuState->SpecialRegisters.Tr);
}
/**
* Restores the executing processor's state.
*
* @param TrapFrame
* Supplies a pointer to the hardware trap frame that will be populated with the restored volatile state.
*
* @param ExceptionFrame
* Supplies a pointer to the exception frame that will be populated with the restored non-volatile state.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
KE::Processor::RestoreProcessorState(OUT PKTRAP_FRAME TrapFrame,
OUT PKEXCEPTION_FRAME ExceptionFrame)
{
PKPROCESSOR_CONTROL_BLOCK Prcb;
/* Retrieve current processor control block */
Prcb = GetCurrentProcessorControlBlock();
/* Restore processor context */
RestoreProcessorContext(TrapFrame, ExceptionFrame, &Prcb->ProcessorState.ContextFrame,
CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS);
/* Restore processor control registers */
RestoreProcessorControlState(&Prcb->ProcessorState);
}
/**
* Constructs a standardized processor context from the hardware trap and exception frames.
*
* @param TrapFrame
* Supplies a pointer to the trap frame containing volatile processor state, control registers and debug
* registers saved at the time of the interrupt or exception.
*
* @param ExceptionFrame
* Supplies a pointer to the exception frame containing non-volatile integer and floating-point registers.
*
* @param ContextFrame
* Supplies a pointer to the context frame that will receive the processor state.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
KE::Processor::SaveProcessorContext(IN PKTRAP_FRAME TrapFrame,
IN PKEXCEPTION_FRAME ExceptionFrame,
IN OUT PCONTEXT ContextFrame)
{
/* Elevate RunLevel to APC_LEVEL to prevent thread preemption */
KE::RaiseRunLevel RunLevel(APC_LEVEL);
/* Check if control registers are requested */
if(ContextFrame->ContextFlags & CONTEXT_CONTROL)
{
/* Copy instruction pointer, stack pointer, and CPU status flags */
ContextFrame->Flags = TrapFrame->Flags;
ContextFrame->Ebp = TrapFrame->Ebp;
ContextFrame->Eip = TrapFrame->Eip;
ContextFrame->Esp = TrapFrame->Esp;
ContextFrame->SegCs = TrapFrame->SegCs;
ContextFrame->SegSs = TrapFrame->SegSs;
}
/* Check if general-purpose integer registers are requested */
if(ContextFrame->ContextFlags & CONTEXT_INTEGER)
{
/* Copy integer registers directly from the trap frame */
ContextFrame->Eax = TrapFrame->Eax;
ContextFrame->Ebx = TrapFrame->Ebx;
ContextFrame->Ecx = TrapFrame->Ecx;
ContextFrame->Edx = TrapFrame->Edx;
ContextFrame->Edi = TrapFrame->Edi;
ContextFrame->Esi = TrapFrame->Esi;
}
/* Check if segment registers are requested */
if(ContextFrame->ContextFlags & CONTEXT_SEGMENTS)
{
/* Populate segment selectors with standard Ring 3 values */
TrapFrame->SegDs = KGDT_R3_DATA | RPL_MASK;
TrapFrame->SegEs = KGDT_R3_DATA | RPL_MASK;
TrapFrame->SegFs = KGDT_R0_PB;
TrapFrame->SegGs = 0;
}
/* Check if floating-point registers are requested and if running in user mode */
if((ContextFrame->ContextFlags & CONTEXT_FLOATING_POINT) && ((TrapFrame->SegCs & MODE_MASK) == UserMode))
{
/* No user-mode support */
UNIMPLEMENTED;
}
/* Check if debug registers are requested */
if(ContextFrame->ContextFlags & CONTEXT_DEBUG_REGISTERS)
{
/* Copy debug registers */
ContextFrame->Dr0 = TrapFrame->Dr0;
ContextFrame->Dr1 = TrapFrame->Dr1;
ContextFrame->Dr2 = TrapFrame->Dr2;
ContextFrame->Dr3 = TrapFrame->Dr3;
ContextFrame->Dr6 = TrapFrame->Dr6;
ContextFrame->Dr7 = TrapFrame->Dr7;
}
/* Check if extended registers are requested and if running in user mode */
if((ContextFrame->ContextFlags & CONTEXT_EXTENDED_REGISTERS) && ((TrapFrame->SegCs & MODE_MASK) == UserMode))
{
/* No user-mode support */
UNIMPLEMENTED;
}
}
/**
* Saves the current processor's low-level hardware control state.
*
* @param State
* Supplies a pointer to the processor state block that will receive processor's control data.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
KE::Processor::SaveProcessorControlState(OUT PKPROCESSOR_STATE CpuState)
{
/* Save CR registers */
CpuState->SpecialRegisters.Cr0 = AR::CpuFunctions::ReadControlRegister(0);
@@ -211,3 +415,36 @@ KE::Processor::SaveProcessorState(OUT PKPROCESSOR_STATE CpuState)
AR::CpuFunctions::StoreLocalDescriptorTable(&CpuState->SpecialRegisters.Ldtr);
AR::CpuFunctions::StoreTaskRegister(&CpuState->SpecialRegisters.Tr);
}
/**
* Captures the executing processor's state.
*
* @param TrapFrame
* Supplies a pointer to the hardware trap frame containing the processor's volatile state.
*
* @param ExceptionFrame
* Supplies a pointer to the exception frame containing the processor's non-volatile state.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
KE::Processor::SaveProcessorState(IN PKTRAP_FRAME TrapFrame,
IN PKEXCEPTION_FRAME ExceptionFrame)
{
PKPROCESSOR_CONTROL_BLOCK Prcb;
/* Retrieve current processor control block */
Prcb = GetCurrentProcessorControlBlock();
/* Set context flags to save whole full context and debug registers */
Prcb->ProcessorState.ContextFrame.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
/* Save processor context */
SaveProcessorContext(TrapFrame, ExceptionFrame, &Prcb->ProcessorState.ContextFrame);
/* Save processor control registers */
SaveProcessorControlState(&Prcb->ProcessorState);
}

247
xtoskrnl/ke/ipi.cc Normal file
View File

@@ -0,0 +1,247 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/ke/ipi.cc
* DESCRIPTION: Interprocessor interrupt support
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#include <xtos.hh>
/**
* Handles an IPI interrupt.
*
* @param TrapFrame
* Supplies a pointer to the processor's trap frame captured at the moment the interrupt was delivered.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTCDECL
VOID
KE::Ipi::HandleIpiInterrupt(IN PKTRAP_FRAME TrapFrame)
{
KRUNLEVEL RunLevel;
/* Start the interrupt */
HL::Irq::BeginSystemInterrupt(IPI_LEVEL, &RunLevel);
/* Call the IPI service routine */
HandleIpiService(TrapFrame, NULLPTR);
/* End the interrupt */
HL::Irq::EndInterrupt(TrapFrame, RunLevel);
}
/**
* Services an incoming Inter-Processor Interrupt (IPI).
*
* @param TrapFrame
* Supplies a pointer to the trap frame representing the processor state at the time of the interrupt.
*
* @param ExceptionFrame
* Supplies a pointer to the exception frame.
*
* @return This routine returns TRUE if a standard IPI request (other than IPI_FREEZE) was processed,
* or FALSE otherwise.
*
* @since XT 1.0
*/
XTAPI
BOOLEAN
KE::Ipi::HandleIpiService(IN PKTRAP_FRAME TrapFrame,
IN PKEXCEPTION_FRAME ExceptionFrame)
{
PKPROCESSOR_CONTROL_BLOCK Prcb;
LONG_PTR RequestSummary;
/* Get processor control block */
Prcb = KE::Processor::GetCurrentProcessorControlBlock();
/* Atomically retrieve and clear the pending IPI request summary */
RequestSummary = RTL::Atomic::Exchange64((PLONG_PTR)&Prcb->RequestSummary, 0);
/* Check if an Asynchronous Procedure Call (APC) interrupt was requested */
if((RequestSummary & IPI_APC) != 0)
{
/* Dispatch a software interrupt to process the APC queue */
HL::Irq::SendSoftwareInterrupt(APC_LEVEL);
}
/* Check if a Deferred Procedure Call (DPC) interrupt was requested */
if((RequestSummary & IPI_DPC) != 0)
{
/* Flag the DPC request in the PRCB and dispatch a software interrupt */
Prcb->DpcInterruptRequested = TRUE;
HL::Irq::SendSoftwareInterrupt(DISPATCH_LEVEL);
}
/* Check if the IPI packet is ready to be processed */
if((RequestSummary & IPI_PACKET_READY) != 0)
{
UNIMPLEMENTED;
}
/* Check if a synchronous inter-processor event was requested */
if((RequestSummary & IPI_SYNC_REQUEST) != 0)
{
UNIMPLEMENTED;
}
/* Check if a debugger freeze request was issued */
if((RequestSummary & IPI_FREEZE) != 0)
{
/* Suspend the current processor execution */
KE::Crash::FreezeCurrentExecution(TrapFrame, ExceptionFrame);
}
/* Return TRUE if any standard execution requests were serviced, excluding freeze events */
return (RequestSummary & ~IPI_FREEZE) != 0;
}
/**
* Broadcasts an Inter-Processor Interrupt (IPI) to all active processors in the system.
*
* @param Request
* Supplies the logical request operation flags to be merged into the target processors' request summaries.
*
* @param Self
* Specifies whether the broadcast IPI should also be delivered to the originating processor.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
KE::Ipi::SendBroadcastIpi(IN ULONG Request,
IN BOOLEAN Self)
{
PKPROCESSOR_BLOCK CurrentProcessorBlock, TargetProcessorBlock;
ULONG CpuCount, Index;
BOOLEAN Interrupts;
/* Get the number of installed CPUs */
CpuCount = KE::Processor::GetInstalledCpus();
/* Check if there are any processors to broadcast to */
if(CpuCount <= 1 && !Self)
{
/* There are no other processors, return */
return;
}
/* Check whether interrupts are enabled */
Interrupts = AR::CpuFunctions::InterruptsEnabled();
/* Disable interrupts */
AR::CpuFunctions::ClearInterruptFlag();
/* Get the current processor block */
CurrentProcessorBlock = KE::Processor::GetCurrentProcessorBlock();
/* Iterate over all logical CPUs */
for(Index = 0; Index < CpuCount; Index++)
{
/* Retrieve the target processor block by its Logical CPU Number */
TargetProcessorBlock = KE::Processor::GetProcessorBlock(Index);
/* Only target processors that exist and have successfully started */
if(TargetProcessorBlock != NULLPTR && TargetProcessorBlock->Started)
{
/* Check if this processor originated the broadcast */
if(TargetProcessorBlock->HardwareId == CurrentProcessorBlock->HardwareId)
{
/* Check if this is a self broadcast */
if(Self)
{
/* Update the logical request summary and dispatch a physical IPI to the current processor */
RTL::Atomic::Or64((PLONG_PTR)&TargetProcessorBlock->Prcb.RequestSummary, Request);
HL::Pic::SendSelfIpi(APIC_VECTOR_IPI);
}
}
else
{
/* Update the logical request summary and dispatch a physical IPI to the target processor */
RTL::Atomic::Or64((PLONG_PTR)&TargetProcessorBlock->Prcb.RequestSummary, Request);
HL::Pic::SendIpi(TargetProcessorBlock->HardwareId, APIC_VECTOR_IPI, APIC_DM_FIXED,
APIC_DSH_Destination, APIC_TGM_EDGE);
}
}
}
/* Check whether interrupts need to be re-enabled */
if(Interrupts)
{
/* Re-enable interrupts */
AR::CpuFunctions::SetInterruptFlag();
}
}
/**
* Sends an Inter-Processor Interrupt (IPI) to a specific set of target processors.
*
* @param Request
* Supplies the logical request operation flags to be merged into the target processors' * request summaries.
*
* @param TargetSet
* Supplies a pointer to the affinity map defining the processors to be interrupted.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
KE::Ipi::SendIpi(IN ULONG Request,
IN PKAFFINITY_MAP TargetSet)
{
PKPROCESSOR_BLOCK ProcessorBlock;
ULONG BlockIndex, CpuIndex;
KAFFINITY AffinityBlock;
BOOLEAN Interrupts;
/* Check whether interrupts are enabled */
Interrupts = AR::CpuFunctions::InterruptsEnabled();
/* Disable interrupts */
AR::CpuFunctions::ClearInterruptFlag();
/* Iterate through all blocks within the target affinity map */
for(BlockIndex = 0; BlockIndex < TargetSet->Size; BlockIndex++)
{
/* Retrieve the current affinity block */
AffinityBlock = TargetSet->Bitmap[BlockIndex];
/* Loop until all set bits in the current block have been processed */
while(AffinityBlock != 0)
{
/* Find the index of the lowest set bit representing a target CPU */
AR::CpuFunctions::ScanForwardBit(&CpuIndex, AffinityBlock);
/* Retrieve the target processor block */
ProcessorBlock = KE::Processor::GetProcessorBlock((BlockIndex * 64) + CpuIndex);
/* Ensure the processor block exists */
if(ProcessorBlock != NULLPTR)
{
/* Update the logical request summary and dispatch the physical IPI */
RTL::Atomic::Or64((PLONG_PTR)&ProcessorBlock->Prcb.RequestSummary, Request);
HL::Pic::SendIpi(ProcessorBlock->HardwareId, APIC_VECTOR_IPI, APIC_DM_FIXED,
APIC_DSH_Destination, APIC_TGM_EDGE);
}
/* Clear the processed bit to move on to the next CPU */
AffinityBlock &= ~((KAFFINITY)1 << CpuIndex);
}
}
/* Check whether interrupts need to be re-enabled */
if(Interrupts)
{
/* Re-enable interrupts */
AR::CpuFunctions::SetInterruptFlag();
}
}

View File

@@ -9,6 +9,21 @@
#include <xtos.hh>
/**
* Retrieves the pointer to the global Idle process.
*
* @return Returns a pointer to the Idle process.
*
* @since XT 1.0
*/
XTAPI
PKPROCESS
KE::KProcess::GetIdleProcess(VOID)
{
/* Return pointer to the idle process */
return &InitialProcess.ProcessControlBlock;
}
/**
* Retrieves a pointer to the system's initial executive process object.
*
@@ -23,6 +38,58 @@ KE::KProcess::GetInitialProcess(VOID)
return &InitialProcess;
}
/**
* Initializes the system-wide Idle Process.
*
* @param Process
* Supplies a pointer to the KPROCESS structure representing the idle process.
*
* @param DirectoryTable
* Supplies a pointer to the initial hardware page directory table for the process.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
XTSTATUS
KE::KProcess::InitializeIdleProcess(IN OUT PKPROCESS IdleProcess,
IN PULONG_PTR DirectoryTable)
{
XTSTATUS Status;
ULONG Cpus;
/* Get the number of natively installed CPUs */
Cpus = KE::Processor::GetInstalledCpus();
/* Allocate and initialize the baseline affinity map for the process */
Status = KE::Affinity::CreateAffinityMap(Cpus, &IdleProcess->Affinity);
if(Status != STATUS_SUCCESS)
{
/* Affinity map allocation failed, return status code */
return Status;
}
/* Allocate and initialize the dynamic map used to track actively running CPUs */
Status = KE::Affinity::CreateAffinityMap(Cpus, &IdleProcess->ActiveProcessors);
if(Status != STATUS_SUCCESS)
{
/* Affinity map allocation failed, free affinity map and return status code */
KE::Affinity::DestroyAffinityMap(IdleProcess->Affinity);
return Status;
}
/* Set Idle Process affinity */
KE::Affinity::SetAllProcessorsAffinity(IdleProcess->Affinity);
/* Initialize Idle process */
KE::KProcess::InitializeProcess(IdleProcess, 0, NULLPTR, DirectoryTable, FALSE);
IdleProcess->Quantum = MAXCHAR;
/* Return success */
return STATUS_SUCCESS;
}
/**
* Initializes the process.
*
@@ -32,8 +99,8 @@ KE::KProcess::GetInitialProcess(VOID)
* @param Priority
* Specifies the process priority.
*
* @param Affinity
* Specifies a process affinity designating processors on which process can run.
* @param AffinityMap
* Specifies a process affinity map designating processors on which process can run.
*
* @param DirectoryTable
* Supplies a pointer to the directory table.
@@ -49,11 +116,13 @@ XTAPI
VOID
KE::KProcess::InitializeProcess(IN OUT PKPROCESS Process,
IN KPRIORITY Priority,
IN KAFFINITY Affinity,
IN PKAFFINITY_MAP AffinityMap,
IN PULONG_PTR DirectoryTable,
IN BOOLEAN Alignment)
{
/* Initialize process dispatcher header */
Process->Header.SignalState = 0;
Process->Header.Size = sizeof(KPROCESS) / sizeof(LONG);
Process->Header.Type = ProcessObject;
/* Initialize process wait list */
@@ -64,15 +133,23 @@ KE::KProcess::InitializeProcess(IN OUT PKPROCESS Process,
RtlInitializeListHead(&Process->ReadyListHead);
RtlInitializeListHead(&Process->ThreadListHead);
/* Check if source affinity map was provided */
if(AffinityMap != NULLPTR && AffinityMap != Process->Affinity)
{
/* Set process affinity */
KE::Affinity::CopyAffinity(Process->Affinity, AffinityMap);
}
/* Set base process properties */
Process->BasePriority = Priority;
Process->Affinity = Affinity;
Process->AutoAlignment = Alignment;
/* Set directory tables */
Process->DirectoryTable[0] = DirectoryTable[0];
Process->DirectoryTable[1] = DirectoryTable[1];
Process->StackCount = MAXSHORT;
/* Set thread quantum */
/* Set the initial stack count and process quantum */
Process->StackCount = MAXSHORT;
Process->Quantum = THREAD_QUANTUM;
/* Set IOPM offset */

View File

@@ -9,9 +9,6 @@
#include <xtos.hh>
/* Use routines from Kernel Library */
using namespace KE;
/**
* This routine starts up the XT kernel. It is called by boot loader.
*
@@ -22,6 +19,7 @@ using namespace KE;
*
* @since XT 1.0
*/
XTCLINK
XTAPI
VOID
KeStartXtSystem(IN PKERNEL_INITIALIZATION_BLOCK Parameters)

View File

@@ -23,6 +23,76 @@ KE::KThread::GetInitialThread(VOID)
return &InitialThread;
}
/**
* Initializes an Idle Thread.
*
* @param IdleProcess
* Supplies a pointer to the global Idle Process container.
*
* @param IdleThread
* Supplies a pointer to the KTHREAD structure being initialized.
*
* @param Prcb
* Supplies a pointer to the Processor Control Block of the target CPU.
*
* @param Stack
* Supplies a pointer to the pre-allocated kernel stack for this thread.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
XTSTATUS
KE::KThread::InitializeIdleThread(IN PKPROCESS IdleProcess,
IN OUT PKTHREAD IdleThread,
IN PKPROCESSOR_CONTROL_BLOCK Prcb,
IN PVOID Stack)
{
XTSTATUS Status;
ULONG Cpus;
/* Get the number of installed CPUs */
Cpus = KE::Processor::GetInstalledCpus();
/* Allocate and initialize the primary affinity map for the thread */
Status = KE::Affinity::CreateAffinityMap(Cpus, &IdleThread->Affinity);
if(Status != STATUS_SUCCESS)
{
/* Affinity map allocation failed, return status code */
return Status;
}
/* Allocate and initialize the user-mode affinity map for the thread */
Status = KE::Affinity::CreateAffinityMap(Cpus, &IdleThread->UserAffinity);
if(Status != STATUS_SUCCESS)
{
/* Affinity map allocation failed, free affinity map and return status code */
KE::Affinity::DestroyAffinityMap(IdleThread->Affinity);
return Status;
}
/* Initialize Idle thread */
KE::KThread::InitializeThread(IdleProcess, IdleThread, NULLPTR, NULLPTR, NULLPTR,
NULLPTR, NULLPTR, Stack, TRUE);
/* Configure Idle thread scheduling parameters */
IdleThread->NextProcessor = Prcb->CpuNumber;
IdleThread->Priority = THREAD_HIGH_PRIORITY;
IdleThread->State = Running;
IdleThread->WaitRunLevel = DISPATCH_LEVEL;
/* Configure thread affinity */
KE::Affinity::SetProcessorAffinity(IdleThread->Affinity, Prcb->CpuNumber);
KE::Affinity::SetProcessorAffinity(IdleThread->UserAffinity, Prcb->CpuNumber);
/* Register CPU as active in the IDLE Process */
KE::Affinity::AtomicSetProcessorAffinity(IdleProcess->ActiveProcessors, Prcb->CpuNumber);
/* Return success */
return STATUS_SUCCESS;
}
/**
* Initializes the thread.
*
@@ -75,8 +145,10 @@ KE::KThread::InitializeThread(IN PKPROCESS Process,
Allocation = FALSE;
/* Initialize thread dispatcher header */
Thread->Header.Type = ThreadObject;
Thread->Header.SignalState = 0;
Thread->Header.Size = sizeof(KTHREAD) / sizeof(LONG);
Thread->Header.DebugActive = FALSE;
Thread->Header.Type = ThreadObject;
/* Initialize thread wait list */
RTL::LinkedList::InitializeListHead(&Thread->Header.WaitListHead);
@@ -99,15 +171,18 @@ KE::KThread::InitializeThread(IN PKPROCESS Process,
/* Set priority adjustment reason */
Thread->AdjustReason = AdjustNone;
/* Set the thread service table */
Thread->ServiceTable = KE::SystemServices::GetSystemServicesDescriptorTable();
/* Initialize thread lock */
KE::SpinLock::InitializeSpinLock(&Thread->ThreadLock);
/* Initialize thread APC */
Thread->ApcStatePointer[0] = &Thread->ApcState;
Thread->ApcStatePointer[1] = &Thread->SavedApcState;
Thread->ApcQueueable = TRUE;
Thread->ApcState.Process = Process;
Thread->Process = Process;
Thread->ApcStateIndex = OriginalApcEnvironment;
Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->ApcState;
Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->SavedApcState;
/* Initialize APC list heads */
RTL::LinkedList::InitializeListHead(&Thread->ApcState.ApcListHead[KernelMode]);
@@ -132,8 +207,9 @@ KE::KThread::InitializeThread(IN PKPROCESS Process,
TimerWaitBlock->WaitListEntry.Flink = &(&Thread->Timer)->Header.WaitListHead;
TimerWaitBlock->WaitListEntry.Blink = &(&Thread->Timer)->Header.WaitListHead;
/* Initialize Thread Environment Block*/
/* Initialize Thread Environment Block and set owner process */
Thread->EnvironmentBlock = (PTHREAD_ENVIRONMENT_BLOCK)EnvironmentBlock;
Thread->Process = Process;
/* Make sure there is a valid stack available */
if(!Stack)
@@ -150,6 +226,7 @@ KE::KThread::InitializeThread(IN PKPROCESS Process,
Allocation = TRUE;
}
/* Setup thread stack */
Thread->InitialStack = Stack;
Thread->StackBase = Stack;
Thread->StackLimit = (PVOID)((ULONG_PTR)Stack - KERNEL_STACK_SIZE);
@@ -200,7 +277,7 @@ KE::KThread::InitializeThread(IN PKPROCESS Process,
*/
XTAPI
VOID
KE::KThread::StartThread(IN PKTHREAD Thread)
KE::KThread::StartThread(IN OUT PKTHREAD Thread)
{
UNIMPLEMENTED;
}

25
xtoskrnl/ke/sysserv.cc Normal file
View File

@@ -0,0 +1,25 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/ke/sysserv.cc
* DESCRIPTION: System Services Descriptor Table
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#include <xtos.hh>
/**
* Retrieves a pointer to the System Services Descriptor Table.
*
* @return This routine returns a pointer to the system services descriptor table.
*
* @since XT 1.0
*/
XTAPI
PKSERVICE_DESCRIPTOR_TABLE
KE::SystemServices::GetSystemServicesDescriptorTable(VOID)
{
/* Return NULLPTR as the system services table is not yet implemented */
return NULLPTR;
}

View File

@@ -152,6 +152,7 @@ KE::SystemTime::UpdateSystemTime(IN PKTRAP_FRAME TrapFrame,
IN KRUNLEVEL RunLevel)
{
LARGE_INTEGER InterruptTime, SystemTime;
PKPROCESSOR_CONTROL_BLOCK ControlBlock;
LONG CurrentTickOffset;
/* Advance the global interrupt time on every hardware tick */
@@ -162,6 +163,12 @@ KE::SystemTime::UpdateSystemTime(IN PKTRAP_FRAME TrapFrame,
/* Atomically consume the current tick budget and retrieve the pre-decrement value */
CurrentTickOffset = RTL::Atomic::ExchangeAdd32((PLONG)&TickOffset, -(LONG)Increment);
/* Retrieve the current processor control block */
ControlBlock = KE::Processor::GetCurrentProcessorControlBlock();
/* Verify the system timer expiration */
KE::Timer::VerifySystemTimerExpiration(ControlBlock, TrapFrame, InterruptTime);
/* Determine whether the accumulated increments have crossed the full tick boundary */
if(CurrentTickOffset <= (LONG)Increment)
{
@@ -170,8 +177,9 @@ KE::SystemTime::UpdateSystemTime(IN PKTRAP_FRAME TrapFrame,
SystemTime.QuadPart += TimeAdjustment;
KE::SharedData::SetSystemTime(SystemTime);
/* Update the tick count */
/* Update the tick count and reverify the system timer expiration */
KE::SharedData::IncrementTickCount();
KE::Timer::VerifySystemTimerExpiration(ControlBlock, TrapFrame, InterruptTime);
/* Reload the tick offset accumulator for the next full tick period */
TickOffset += MaximumIncrement;
@@ -179,4 +187,9 @@ KE::SystemTime::UpdateSystemTime(IN PKTRAP_FRAME TrapFrame,
/* Update processor and thread runtime accounting */
KE::Dispatcher::UpdateRunTime(TrapFrame, RunLevel);
}
else
{
/* Increment the interrupt count */
ControlBlock->InterruptCount++;
}
}

View File

@@ -4,6 +4,7 @@
* FILE: xtoskrnl/ke/timer.cc
* DESCRIPTION: Kernel timer object support
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
* Aiken Harris <harraiken91@gmail.com>
*/
#include <xtos.hh>
@@ -156,6 +157,25 @@ KE::Timer::QueryTimer(IN PKTIMER Timer)
return DueTime;
}
/**
* Removes a specified timer from the timer list.
*
* @param Timer
* Supplies a pointer to a timer object.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
KE::Timer::RemoveTimer(IN OUT PKTIMER Timer)
{
/* Remove the timer from the list */
Timer->Header.Inserted = FALSE;
RTL::LinkedList::RemoveEntryList(&Timer->TimerListEntry);
}
/**
* Sets the supplied timer to expire at the specified time.
*
@@ -186,10 +206,17 @@ KE::Timer::SetTimer(IN PKTIMER Timer,
}
/**
* Removes a specified timer from the timer list.
* Verifies if any system timers have expired for the current tick and requests a software
* DISPATCH interrupt to process them if necessary.
*
* @param Timer
* Supplies a pointer to a timer object.
* @param Prcb
* Supplies a pointer to the current Processor Control Block.
*
* @param TrapFrame
* Supplies a pointer to the trap frame representing the interrupted context.
*
* @param Time
* Supplies the current absolute interrupt time.
*
* @return This routine does not return any value.
*
@@ -197,9 +224,37 @@ KE::Timer::SetTimer(IN PKTIMER Timer,
*/
XTAPI
VOID
KE::Timer::RemoveTimer(IN OUT PKTIMER Timer)
KE::Timer::VerifySystemTimerExpiration(IN PKPROCESSOR_CONTROL_BLOCK Prcb,
IN PKTRAP_FRAME TrapFrame,
IN LARGE_INTEGER Time)
{
/* Remove the timer from the list */
Timer->Header.Inserted = FALSE;
RTL::LinkedList::RemoveEntryList(&Timer->TimerListEntry);
LARGE_INTEGER TickCount;
ULONG TimerHand;
PKTIMER Timer;
/* Retrieve the current system tick count and calculate the index into the timer table */
TickCount = KE::SharedData::GetTickCount();
TimerHand = TickCount.LowPart & (KTIMER_TABLE_SIZE - 1);
/* Check if there are any active timers scheduled */
if(!RTL::LinkedList::ListEmpty(&TimerTableListHead[TimerHand]))
{
/* Retrieve the first timer object from the list */
Timer = CONTAIN_RECORD((&TimerTableListHead[TimerHand])->Flink, KTIMER, TimerListEntry);
/* Check if the timer due time has been reached */
if(Timer->DueTime.QuadPart <= Time.QuadPart)
{
/* Ensure there is no pending timer expiration request */
if(!Prcb->TimerRequest)
{
/* Register the timer expiration request and record a timer slot */
Prcb->TimerRequest = (ULONG_PTR)TrapFrame;
Prcb->TimerHand = TimerHand;
/* Request a DPC to safely retire the timer */
HL::Irq::SendSoftwareInterrupt(DISPATCH_LEVEL);
}
}
}
}

View File

@@ -176,6 +176,7 @@ MM::Pte::MapP5E(IN PVOID StartAddress,
IN PMMP5E TemplateP5e)
{
PMMP5E EndSpace, PointerP5e;
PFN_NUMBER PageFrameNumber;
/* Get P5E addresses */
PointerP5e = MM::Paging::GetP5eAddress(StartAddress);
@@ -187,8 +188,18 @@ MM::Pte::MapP5E(IN PVOID StartAddress,
/* Check if P5E is already mapped */
if(!MM::Paging::PteValid(PointerP5e))
{
/* Map P5E */
MM::Paging::SetPte(TemplateP5e, MM::Pfn::AllocateBootstrapPages(1), 0);
/* Attempt to allocate a physical page from the PFN database */
PageFrameNumber = MM::Pfn::AllocatePhysicalPage(0);
/* Check if the primary allocation failed */
if(!PageFrameNumber)
{
/* Allocate a physical page from the fallback allocator */
PageFrameNumber = MM::Pfn::AllocateBootstrapPages(1);
}
/* Update the template with new page frame and write the PTE */
MM::Paging::SetPte(TemplateP5e, PageFrameNumber, 0);
*PointerP5e = *TemplateP5e;
/* Clear the page table */
@@ -223,6 +234,7 @@ MM::Pte::MapPPE(IN PVOID StartAddress,
IN PMMPPE TemplatePpe)
{
PMMPPE EndSpace, PointerPpe;
PFN_NUMBER PageFrameNumber;
/* Get PPE addresses */
PointerPpe = MM::Paging::GetPpeAddress(StartAddress);
@@ -234,8 +246,18 @@ MM::Pte::MapPPE(IN PVOID StartAddress,
/* Check if PPE is already mapped */
if(!MM::Paging::PteValid(PointerPpe))
{
/* Map PPE */
MM::Paging::SetPte(TemplatePpe, MM::Pfn::AllocateBootstrapPages(1), 0);
/* Attempt to allocate a physical page from the PFN database */
PageFrameNumber = MM::Pfn::AllocatePhysicalPage(0);
/* Check if the primary allocation failed */
if(!PageFrameNumber)
{
/* Allocate a physical page from the fallback allocator */
PageFrameNumber = MM::Pfn::AllocateBootstrapPages(1);
}
/* Update the template with new page frame and write the PTE */
MM::Paging::SetPte(TemplatePpe, PageFrameNumber, 0);
*PointerPpe = *TemplatePpe;
/* Clear the page table */
@@ -270,6 +292,7 @@ MM::Pte::MapPXE(IN PVOID StartAddress,
IN PMMPXE TemplatePxe)
{
PMMPXE EndSpace, PointerPxe;
PFN_NUMBER PageFrameNumber;
/* Get PXE addresses */
PointerPxe = MM::Paging::GetPxeAddress(StartAddress);
@@ -281,8 +304,18 @@ MM::Pte::MapPXE(IN PVOID StartAddress,
/* Check if PTE is already mapped */
if(!MM::Paging::PteValid(PointerPxe))
{
/* Map PTE */
MM::Paging::SetPte(TemplatePxe, MM::Pfn::AllocateBootstrapPages(1), 0);
/* Attempt to allocate a physical page from the PFN database */
PageFrameNumber = MM::Pfn::AllocatePhysicalPage(0);
/* Check if the primary allocation failed */
if(!PageFrameNumber)
{
/* Allocate a physical page from the fallback allocator */
PageFrameNumber = MM::Pfn::AllocateBootstrapPages(1);
}
/* Update the template with new page frame and write the PTE */
MM::Paging::SetPte(TemplatePxe, PageFrameNumber, 0);
*PointerPxe = *TemplatePxe;
/* Clear the page table */

View File

@@ -60,6 +60,12 @@ LOADER_MEMORY_DESCRIPTOR MM::HardwarePool::HardwareAllocationDescriptors[MM_HARD
/* Live address of kernel's hardware heap */
PVOID MM::HardwarePool::HardwareHeapStart = MM_HARDWARE_HEAP_START_ADDRESS;
/* Physical address of kernel's low memory region */
PHYSICAL_ADDRESS MM::HardwarePool::LowMemoryPhysicalAddress;
/* Virtual address of kernel's low memory region */
PVOID MM::HardwarePool::LowMemoryVirtualAddress;
/* Number of used hardware allocation descriptors */
ULONG MM::HardwarePool::UsedHardwareAllocationDescriptors = 0;

View File

@@ -150,8 +150,11 @@ MM::HardwarePool::AllocateHardwareMemory(IN PFN_NUMBER PageCount,
/**
* Allocates a physical page in low memory (addressable in real-mode) and maps it into the virtual address space.
*
* @param MemoryAddress
* Supplies a pointer to a variable that receives the identity-mapped virtual address of the allocated memory.
* @param PhysicalAddress
* Supplies a pointer to a variable that receives the physical address of the allocated memory.
*
* @param VirtualAddress
* Supplies a pointer to a variable that receives the virtual address of the allocated memory.
*
* @return This routine returns a status code indicating the success or failure of the operation.
*
@@ -159,39 +162,141 @@ MM::HardwarePool::AllocateHardwareMemory(IN PFN_NUMBER PageCount,
*/
XTAPI
XTSTATUS
MM::HardwarePool::AllocateRealModeMemory(IN PFN_NUMBER PageCount,
OUT PVOID *MemoryAddress)
MM::HardwarePool::AllocateLowMemory(OUT PPHYSICAL_ADDRESS PhysicalAddress,
OUT PVOID *VirtualAddress)
{
PHYSICAL_ADDRESS PhysicalAddress;
PFN_NUMBER PageFrameNumber;
PVOID VirtualAddress;
ULONG AllocationPages, TrampolineCodeSize;
PVOID TrampolineCode;
XTSTATUS Status;
/* Check if low memory is already allocated and mapped */
if(LowMemoryVirtualAddress && LowMemoryPhysicalAddress.QuadPart != 0)
{
/* Check if the caller requested the allocated addresses */
if(PhysicalAddress != NULLPTR && VirtualAddress != NULLPTR)
{
/* Set the trampoline physical and virtual address and return success */
*PhysicalAddress = LowMemoryPhysicalAddress;
*VirtualAddress = LowMemoryVirtualAddress;
}
/* Return success */
return STATUS_SUCCESS;
}
/* Get trampoline information */
AR::ProcessorSupport::GetTrampolineInformation(TrampolineApStartup, &TrampolineCode, &TrampolineCodeSize);
/* Verify trampoline information */
if(TrampolineCode == NULLPTR || TrampolineCodeSize == 0)
{
/* Failed to get trampoline information, return error */
return STATUS_UNSUCCESSFUL;
}
/* Compute number of pages for real-mode memory allocation (trampoline + processor start block + temporary stack) */
AllocationPages = CalculateRealModeAllocationPages(TrampolineCodeSize);
/* Allocate physical memory in first 1MB */
Status = AllocateHardwareMemory(PageCount, TRUE, 0x100000, &PhysicalAddress);
Status = AllocateHardwareMemory(AllocationPages, TRUE, 0x100000, &LowMemoryPhysicalAddress);
if(Status != STATUS_SUCCESS)
{
/* Failed to allocate memory, return error */
return Status;
}
/* Calculate virtual address and page frame number */
VirtualAddress = (PVOID)(ULONG_PTR)PhysicalAddress.QuadPart;
PageFrameNumber = PhysicalAddress.QuadPart >> MM_PAGE_SHIFT;
/* Identity map the memory to the virtual address */
Status = MM::Paging::MapVirtualAddress(VirtualAddress, PageFrameNumber, MM_PTE_EXECUTE_READWRITE);
/* Map the memory to the virtual address */
Status = MapHardwareMemory(LowMemoryPhysicalAddress, AllocationPages, FALSE, &LowMemoryVirtualAddress);
if(Status != STATUS_SUCCESS)
{
/* Failed to map memory, return error */
/* Failed to map memory, free memory and return error */
FreeHardwareMemory(LowMemoryPhysicalAddress, AllocationPages);
return Status;
}
/* Set the trampoline virtual address and return success */
*MemoryAddress = VirtualAddress;
/* Check if the caller requested the allocated addresses */
if(PhysicalAddress != NULLPTR && VirtualAddress != NULLPTR)
{
/* Set the trampoline physical and virtual address and return success */
*PhysicalAddress = LowMemoryPhysicalAddress;
*VirtualAddress = LowMemoryVirtualAddress;
}
/* Return success */
return STATUS_SUCCESS;
}
/**
* Computes the total memory allocation size required for the real-mode trampoline execution environment.
*
* @param TrampolineCodeSize
* Supplies the size of the trampoline code in bytes.
*
* @return This routine returns the computed allocation size in pages.
*
* @since XT 1.0
*/
XTAPI
ULONG
MM::HardwarePool::CalculateRealModeAllocationPages(IN ULONG TrampolineCodeSize)
{
ULONG Size;
/* Compute real-mode memory allocation size (trampoline + processor start block + temporary stack) */
Size = TrampolineCodeSize + sizeof(PROCESSOR_START_BLOCK) + 512;
/* Calculate and return number of pages */
return (ULONG)(ROUND_UP(Size, MM_PAGE_SIZE) / MM_PAGE_SIZE);
}
/**
* Releases physical memory allocated for kernel hardware layer.
*
* @param PhysicalAddress
* Supplies the physical address of the memory block to be freed.
*
* @param PageCount
* Supplies the number of pages associated with the allocation descriptor.
*
* @return This routine returns a status code indicating the success or failure of the operation.
*
* @since XT 1.0
*/
XTAPI
XTSTATUS
MM::HardwarePool::FreeHardwareMemory(IN PHYSICAL_ADDRESS PhysicalAddress,
IN PFN_NUMBER PageCount)
{
PLOADER_MEMORY_DESCRIPTOR Descriptor;
PFN_NUMBER BasePage;
ULONG Index;
/* Calculate base page from physical address */
BasePage = PhysicalAddress.QuadPart >> MM_PAGE_SHIFT;
/* Iterate through recorded hardware descriptors to find the matching allocation */
for(Index = 0; Index < UsedHardwareAllocationDescriptors; Index++)
{
/* Get current hardware allocation descriptor */
Descriptor = &HardwareAllocationDescriptors[Index];
/* Verify descriptor properties */
if(Descriptor->MemoryType == LoaderHardwareCachedMemory &&
Descriptor->BasePage == BasePage &&
Descriptor->PageCount == PageCount)
{
/* Make descriptor available again */
Descriptor->MemoryType = LoaderFree;
/* Return success */
return STATUS_SUCCESS;
}
}
/* Descriptors not found, return error */
return STATUS_INVALID_PARAMETER;
}
/**
* Maps physical address to the virtual memory area used by kernel hardware layer.
*
@@ -291,6 +396,46 @@ MM::HardwarePool::MapHardwareMemory(IN PHYSICAL_ADDRESS PhysicalAddress,
return STATUS_SUCCESS;
}
/**
* Establishes a temporary identity mapping for a specified physical memory range to facilitate real-mode execution.
*
* @param PhysicalAddress
* Supplies the physical address of the trampoline memory.
*
* @param Size
* Supplies the size of the trampoline memory allocation.
*
* @return This routine returns a status code indicating the success or failure of the operation.
*
* @since XT 1.0
*/
XTAPI
XTSTATUS
MM::HardwarePool::MapRealModeMemory(IN PHYSICAL_ADDRESS PhysicalAddress,
IN ULONG Pages)
{
PFN_NUMBER Index;
XTSTATUS Status;
/* Identity map each page of the real-mode memory allocation */
for(Index = 0; Index < Pages; Index++)
{
/* Map the current physical page */
Status = MM::Paging::MapVirtualAddress((PVOID)(PhysicalAddress.QuadPart + (Index * MM_PAGE_SIZE)),
(PhysicalAddress.QuadPart >> MM_PAGE_SHIFT) + Index,
MM_PTE_EXECUTE_READWRITE);
if(Status != STATUS_SUCCESS)
{
/* Failed to map the page, unmap previously mapped pages and return the error code */
UnmapRealModeMemory(PhysicalAddress, Index * MM_PAGE_SIZE);
return Status;
}
}
/* Return success */
return STATUS_SUCCESS;
}
/**
* Marks existing mapping as CD/WT to avoid delays in write-back cache.
*
@@ -425,3 +570,34 @@ MM::HardwarePool::UnmapHardwareMemory(IN PVOID VirtualAddress,
/* Return success */
return STATUS_SUCCESS;
}
/**
* Removes the temporary identity mapping for a real-mode memory region.
*
* @param PhysicalAddress
* Supplies the physical address of the trampoline memory.
*
* @param Size
* Supplies the size of the trampoline memory allocation.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
MM::HardwarePool::UnmapRealModeMemory(IN PHYSICAL_ADDRESS PhysicalAddress,
IN ULONG Size)
{
PFN_NUMBER AllocationPages, Index;
/* Calculate number of pages to unmap */
AllocationPages = (ULONG)(ROUND_UP(Size, MM_PAGE_SIZE) / MM_PAGE_SIZE);
/* Iterate over the allocation pages to remove the identity mapping */
for(Index = 0; Index < AllocationPages; Index++)
{
/* Clear the page table entry for the current virtual address */
MM::Paging::ClearPte(MM::Paging::GetPteAddress((PVOID)(PhysicalAddress.QuadPart + (Index * MM_PAGE_SIZE))));
}
}

View File

@@ -232,6 +232,9 @@ XTAPI
VOID
MM::Manager::InitializeMemoryManager(VOID)
{
/* Allocate low memory from the hardware pool before initializing the memory manager */
MM::HardwarePool::AllocateLowMemory(NULLPTR, NULLPTR);
/* Scan memory descriptors provided by the boot loader */
MM::Pfn::ScanMemoryDescriptors();
@@ -256,6 +259,9 @@ MM::Manager::InitializeMemoryManager(VOID)
/* Initialize page table */
MM::Pte::InitializePageTable();
/* Initialize PFN database */
MM::Pfn::InitializePfnDatabase();
/* Initialize system PTE space */
MM::Pte::InitializeSystemPteSpace();
@@ -265,9 +271,6 @@ MM::Manager::InitializeMemoryManager(VOID)
/* Initialize non-paged pool */
MM::Pool::InitializeNonPagedPool();
/* Initialize PFN database */
MM::Pfn::InitializePfnDatabase();
/* Initialize allocations tracking tables */
MM::Allocator::InitializeAllocationsTracking();
MM::Allocator::InitializeBigAllocationsTracking();

View File

@@ -242,6 +242,7 @@ MM::Pte::MapPDE(IN PVOID StartAddress,
IN PMMPDE TemplatePde)
{
PMMPDE EndSpace, PointerPde;
PFN_NUMBER PageFrameNumber;
/* Get PDE addresses */
PointerPde = MM::Paging::GetPdeAddress(StartAddress);
@@ -253,8 +254,18 @@ MM::Pte::MapPDE(IN PVOID StartAddress,
/* Check if PDE is already mapped */
if(!MM::Paging::PteValid(PointerPde))
{
/* Map PDE */
MM::Paging::SetPte(TemplatePde, MM::Pfn::AllocateBootstrapPages(1), 0);
/* Attempt to allocate a physical page from the PFN database */
PageFrameNumber = MM::Pfn::AllocatePhysicalPage(0);
/* Check if the primary allocation failed */
if(!PageFrameNumber)
{
/* Allocate a physical page from the fallback allocator */
PageFrameNumber = MM::Pfn::AllocateBootstrapPages(1);
}
/* Update the template with new page frame and write the PTE */
MM::Paging::SetPte(TemplatePde, PageFrameNumber, 0);
MM::Paging::WritePte(PointerPde, *TemplatePde);
/* Clear the page table */
@@ -289,6 +300,7 @@ MM::Pte::MapPTE(IN PVOID StartAddress,
IN PMMPTE TemplatePte)
{
PMMPTE EndSpace, PointerPte;
PFN_NUMBER PageFrameNumber;
/* Get PTE addresses */
PointerPte = MM::Paging::GetPteAddress(StartAddress);
@@ -300,8 +312,18 @@ MM::Pte::MapPTE(IN PVOID StartAddress,
/* Check if PTE is already mapped */
if(!MM::Paging::PteValid(PointerPte))
{
/* Map PTE */
MM::Paging::SetPte(TemplatePte, MM::Pfn::AllocateBootstrapPages(1), 0);
/* Attempt to allocate a physical page from the PFN database */
PageFrameNumber = MM::Pfn::AllocatePhysicalPage(0);
/* Check if the primary allocation failed */
if(!PageFrameNumber)
{
/* Allocate a physical page from the fallback allocator */
PageFrameNumber = MM::Pfn::AllocateBootstrapPages(1);
}
/* Update the template with new page frame and write the PTE */
MM::Paging::SetPte(TemplatePte, PageFrameNumber, 0);
MM::Paging::WritePte(PointerPte, *TemplatePte);
/* Clear the page table */
@@ -313,7 +335,6 @@ MM::Pte::MapPTE(IN PVOID StartAddress,
}
}
/**
* Releases a block of system PTEs into a specified pool.
*

51
xtoskrnl/ps/process.cc Normal file
View File

@@ -0,0 +1,51 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/po/process.cc
* DESCRIPTION: Process Management
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#include <xtos.hh>
/**
* Creates the global IDLE process.
*
* @param Prcb
* Supplies a pointer to the Processor Control Block of the Bootstrap Processor.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
XTSTATUS
PS::Process::CreateIdleProcess(IN PKPROCESSOR_CONTROL_BLOCK Prcb)
{
ULONG_PTR PageDirectory[2];
PKPROCESS IdleProcess;
PKTHREAD IdleThread;
XTSTATUS Status;
/* Get initial IDLE thread */
IdleThread = Prcb->CurrentThread;
/* Get initial IDLE process */
IdleProcess = IdleThread->ApcState.Process;
/* Setup placeholder for page directory entries */
PageDirectory[0] = 0;
PageDirectory[1] = 0;
/* Initialize IDLE process */
Status = KE::KProcess::InitializeIdleProcess(IdleProcess, PageDirectory);
if(Status != STATUS_SUCCESS)
{
/* Failed to initialize IDLE process, return status code */
return Status;
}
/* Initialize IDLE thread */
return KE::KThread::InitializeIdleThread(IdleProcess, IdleThread, Prcb, AR::ProcessorSupport::GetBootStack());
}

63
xtoskrnl/ps/thread.cc Normal file
View File

@@ -0,0 +1,63 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/po/thread.cc
* DESCRIPTION: Thread Management
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#include <xtos.hh>
/**
* Allocates and initializes a per-processor IDLE thread for an Application Processor (AP).
*
* @param Prcb
* Supplies a pointer to the Processor Control Block of the target processor.
*
* @param Stack
* Supplies a pointer to the pre-allocated kernel stack for the new idle thread.
*
* @return This routine returns a status code indicating the success or failure of the operation.
*
* @since XT 1.0
*/
XTAPI
XTSTATUS
PS::Thread::CreateIdleThread(IN PKPROCESSOR_CONTROL_BLOCK Prcb,
IN PVOID Stack)
{
PKPROCESS IdleProcess;
PETHREAD IdleThread;
XTSTATUS Status;
/* Retrieve the global IDLE process container */
IdleProcess = KE::KProcess::GetIdleProcess();
/* Allocate the Executive Thread object */
Status = MM::Allocator::AllocatePool(NonPagedPool, sizeof(ETHREAD), (PVOID*)&IdleThread);
if(Status != STATUS_SUCCESS)
{
/* Memory allocation failed, return the status code */
return Status;
}
/* Zero the allocated memory to prevent uninitialized data */
RTL::Memory::ZeroMemory(IdleThread, sizeof(ETHREAD));
/* Register the new thread within the Processor Control Block */
Prcb->CurrentThread = &IdleThread->ThreadControlBlock;
Prcb->IdleThread = &IdleThread->ThreadControlBlock;
/* Initialize the IDLE thread */
Status = KE::KThread::InitializeIdleThread(IdleProcess, &IdleThread->ThreadControlBlock, Prcb, Stack);
if(Status != STATUS_SUCCESS)
{
/* Failed to initialize the IDLE thread state, free the ETHREAD object and return the status code */
MM::Allocator::FreePool((PVOID)IdleThread);
return Status;
}
/* Return success */
return STATUS_SUCCESS;
}