Compare commits
78 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
f79c9023d8
|
|||
|
97703c7932
|
|||
|
2f5902119d
|
|||
|
7a10135731
|
|||
|
b0074637f8
|
|||
|
1a062ca05f
|
|||
|
c702152cca
|
|||
|
81c799e590
|
|||
|
cf0d7f0a40
|
|||
|
b0d2868f82
|
|||
|
32f0b747a1
|
|||
|
c57aa98923
|
|||
|
429e4ef6f1
|
|||
|
39928f2ef4
|
|||
|
51ec7e3bab
|
|||
|
f3ae70573c
|
|||
|
830f84ab26
|
|||
|
5a9df7ca86
|
|||
|
4bcdcda3a0
|
|||
|
7a27912dac
|
|||
|
cf4b91ac83
|
|||
|
36c3d92399
|
|||
|
6a2a35c008
|
|||
|
a9202f5b57
|
|||
|
4cbefe3a22
|
|||
|
3841ceaf5b
|
|||
|
e2eb784eef
|
|||
|
6078a5ba29
|
|||
|
663f5cd048
|
|||
|
5999906bf0
|
|||
|
1e0c1490fb
|
|||
|
5b0eebdb43
|
|||
|
9e64939de4
|
|||
|
b911670121
|
|||
|
d175a817a5
|
|||
|
b285bc7312
|
|||
|
c8cd198c4e
|
|||
|
95d45f5a0a
|
|||
|
766e4d9603
|
|||
|
a601fd0afa
|
|||
|
cc23e459e0
|
|||
|
d36b678ba1
|
|||
|
43265bcddb
|
|||
|
47d4069d6f
|
|||
|
904df63198
|
|||
|
1df971a71e
|
|||
|
2a413d5717
|
|||
|
9c2357dfe6
|
|||
|
f82562f450
|
|||
|
a33b63842a
|
|||
|
4256a312ae
|
|||
|
678a0f4f48
|
|||
|
7344c5ed4a
|
|||
|
537fbc8af4
|
|||
|
cf25af23d1
|
|||
|
f680830b53
|
|||
|
53a239958f
|
|||
|
f13326ffaf
|
|||
|
75e7760d04
|
|||
|
02d0f3f538
|
|||
|
e2a78389f2
|
|||
|
81fdf1f77a
|
|||
|
631f58bf72
|
|||
|
1d2d66fc83
|
|||
|
34aba8c7c7
|
|||
|
5e764a0d17
|
|||
|
65e86db731
|
|||
|
615d253bb4
|
|||
|
2fcbc7bee8
|
|||
|
2c14da997d
|
|||
|
a7c2182d4a
|
|||
|
0aabc206a1
|
|||
|
7d8b33390a
|
|||
|
5a5604c35d
|
|||
|
addf9addab
|
|||
|
f562aa0874
|
|||
|
19a9dfe7c6
|
|||
|
46594f1fc3
|
@@ -30,7 +30,7 @@ namespace AR
|
|||||||
public:
|
public:
|
||||||
STATIC XTAPI VOID GetTrampolineInformation(IN TRAMPOLINE_TYPE TrampolineType,
|
STATIC XTAPI VOID GetTrampolineInformation(IN TRAMPOLINE_TYPE TrampolineType,
|
||||||
OUT PVOID *TrampolineCode,
|
OUT PVOID *TrampolineCode,
|
||||||
OUT PULONG_PTR TrampolineSize);
|
OUT PULONG TrampolineSize);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ Xtos::EnablePaging(IN PXTBL_PAGE_MAPPING PageMap)
|
|||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
EFI_PHYSICAL_ADDRESS TrampolineAddress;
|
EFI_PHYSICAL_ADDRESS TrampolineAddress;
|
||||||
PXT_TRAMPOLINE_ENTRY TrampolineEntry;
|
PXT_TRAMPOLINE_ENTRY TrampolineEntry;
|
||||||
ULONG_PTR TrampolineSize;
|
ULONG TrampolineSize;
|
||||||
PVOID TrampolineCode;
|
PVOID TrampolineCode;
|
||||||
|
|
||||||
/* Check the configured page map level to set the LA57 state accordingly */
|
/* Check the configured page map level to set the LA57 state accordingly */
|
||||||
|
|||||||
@@ -39,6 +39,9 @@
|
|||||||
#define APIC_VECTOR_PERF 0xFE
|
#define APIC_VECTOR_PERF 0xFE
|
||||||
#define APIC_VECTOR_NMI 0xFF
|
#define APIC_VECTOR_NMI 0xFF
|
||||||
|
|
||||||
|
/* APIC SIPI vector shift */
|
||||||
|
#define APIC_VECTOR_SIPI_SHIFT 12
|
||||||
|
|
||||||
/* APIC destination formats */
|
/* APIC destination formats */
|
||||||
#define APIC_DF_FLAT 0xFFFFFFFF
|
#define APIC_DF_FLAT 0xFFFFFFFF
|
||||||
#define APIC_DF_CLUSTER 0x0FFFFFFF
|
#define APIC_DF_CLUSTER 0x0FFFFFFF
|
||||||
|
|||||||
@@ -132,6 +132,18 @@
|
|||||||
#define CONTEXT_SEGMENTS (CONTEXT_ARCHITECTURE | 0x04)
|
#define CONTEXT_SEGMENTS (CONTEXT_ARCHITECTURE | 0x04)
|
||||||
#define CONTEXT_FLOATING_POINT (CONTEXT_ARCHITECTURE | 0x08)
|
#define CONTEXT_FLOATING_POINT (CONTEXT_ARCHITECTURE | 0x08)
|
||||||
#define CONTEXT_DEBUG_REGISTERS (CONTEXT_ARCHITECTURE | 0x10)
|
#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 */
|
/* Interrupt request levels definitions */
|
||||||
#define PASSIVE_LEVEL 0
|
#define PASSIVE_LEVEL 0
|
||||||
@@ -232,7 +244,7 @@ typedef struct _CONTEXT
|
|||||||
USHORT SegFs;
|
USHORT SegFs;
|
||||||
USHORT SegGs;
|
USHORT SegGs;
|
||||||
USHORT SegSs;
|
USHORT SegSs;
|
||||||
ULONG EFlags;
|
ULONG Flags;
|
||||||
ULONG64 Dr0;
|
ULONG64 Dr0;
|
||||||
ULONG64 Dr1;
|
ULONG64 Dr1;
|
||||||
ULONG64 Dr2;
|
ULONG64 Dr2;
|
||||||
@@ -560,13 +572,27 @@ typedef struct _KPROCESSOR_CONTROL_BLOCK
|
|||||||
ULONG_PTR SetMember;
|
ULONG_PTR SetMember;
|
||||||
CPU_IDENTIFICATION CpuId;
|
CPU_IDENTIFICATION CpuId;
|
||||||
KPROCESSOR_STATE ProcessorState;
|
KPROCESSOR_STATE ProcessorState;
|
||||||
|
KSPIN_LOCK PrcbLock;
|
||||||
KSPIN_LOCK_QUEUE LockQueue[MaximumLock];
|
KSPIN_LOCK_QUEUE LockQueue[MaximumLock];
|
||||||
|
VOLATILE ULONG IpiFrozen;
|
||||||
|
VOLATILE LONG_PTR RequestSummary;
|
||||||
KDPC_DATA DpcData[2];
|
KDPC_DATA DpcData[2];
|
||||||
PVOID DpcStack;
|
PVOID DpcStack;
|
||||||
|
LONG MaximumDpcQueueDepth;
|
||||||
|
ULONG DpcRequestRate;
|
||||||
|
BOOLEAN DpcInterruptRequested;
|
||||||
VOLATILE BOOLEAN DpcRoutineActive;
|
VOLATILE BOOLEAN DpcRoutineActive;
|
||||||
|
ULONG DpcLastCount;
|
||||||
|
VOLATILE ULONG_PTR TimerHand;
|
||||||
VOLATILE ULONG_PTR TimerRequest;
|
VOLATILE ULONG_PTR TimerRequest;
|
||||||
ULONG_PTR MultiThreadProcessorSet;
|
ULONG_PTR MultiThreadProcessorSet;
|
||||||
SINGLE_LIST_ENTRY DeferredReadyListHead;
|
SINGLE_LIST_ENTRY DeferredReadyListHead;
|
||||||
|
ULONG InterruptCount;
|
||||||
|
ULONG KernelTime;
|
||||||
|
ULONG UserTime;
|
||||||
|
ULONG DpcTime;
|
||||||
|
ULONG InterruptTime;
|
||||||
|
ULONG AdjustDpcThreshold;
|
||||||
PROCESSOR_POWER_STATE PowerState;
|
PROCESSOR_POWER_STATE PowerState;
|
||||||
ULONG ProfilingCountdown;
|
ULONG ProfilingCountdown;
|
||||||
} KPROCESSOR_CONTROL_BLOCK, *PKPROCESSOR_CONTROL_BLOCK;
|
} KPROCESSOR_CONTROL_BLOCK, *PKPROCESSOR_CONTROL_BLOCK;
|
||||||
|
|||||||
@@ -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_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 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 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_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_COMMIT_PAGE_MAP)(IN PXTBL_PAGE_MAPPING PageMap);
|
||||||
typedef EFI_STATUS (XTCDECL *PBL_CLOSE_VOLUME)(IN PEFI_HANDLE VolumeHandle);
|
typedef EFI_STATUS (XTCDECL *PBL_CLOSE_VOLUME)(IN PEFI_HANDLE VolumeHandle);
|
||||||
|
|||||||
@@ -45,6 +45,9 @@
|
|||||||
#define APIC_VECTOR_PERF 0xFE
|
#define APIC_VECTOR_PERF 0xFE
|
||||||
#define APIC_VECTOR_NMI 0xFF
|
#define APIC_VECTOR_NMI 0xFF
|
||||||
|
|
||||||
|
/* APIC SIPI vector shift */
|
||||||
|
#define APIC_VECTOR_SIPI_SHIFT 12
|
||||||
|
|
||||||
/* APIC destination formats */
|
/* APIC destination formats */
|
||||||
#define APIC_DF_FLAT 0xFFFFFFFF
|
#define APIC_DF_FLAT 0xFFFFFFFF
|
||||||
#define APIC_DF_CLUSTER 0x0FFFFFFF
|
#define APIC_DF_CLUSTER 0x0FFFFFFF
|
||||||
|
|||||||
@@ -154,6 +154,19 @@
|
|||||||
#define CONTEXT_FLOATING_POINT (CONTEXT_ARCHITECTURE | 0x08)
|
#define CONTEXT_FLOATING_POINT (CONTEXT_ARCHITECTURE | 0x08)
|
||||||
#define CONTEXT_DEBUG_REGISTERS (CONTEXT_ARCHITECTURE | 0x10)
|
#define CONTEXT_DEBUG_REGISTERS (CONTEXT_ARCHITECTURE | 0x10)
|
||||||
#define CONTEXT_EXTENDED_REGISTERS (CONTEXT_ARCHITECTURE | 0x20)
|
#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 */
|
/* Interrupt request levels definitions */
|
||||||
#define PASSIVE_LEVEL 0
|
#define PASSIVE_LEVEL 0
|
||||||
@@ -291,7 +304,7 @@ typedef struct _CONTEXT
|
|||||||
ULONG Ebp;
|
ULONG Ebp;
|
||||||
ULONG Eip;
|
ULONG Eip;
|
||||||
ULONG SegCs;
|
ULONG SegCs;
|
||||||
ULONG EFlags;
|
ULONG Flags;
|
||||||
ULONG Esp;
|
ULONG Esp;
|
||||||
ULONG SegSs;
|
ULONG SegSs;
|
||||||
UCHAR ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];
|
UCHAR ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];
|
||||||
@@ -519,13 +532,27 @@ typedef struct _KPROCESSOR_CONTROL_BLOCK
|
|||||||
ULONG_PTR SetMember;
|
ULONG_PTR SetMember;
|
||||||
CPU_IDENTIFICATION CpuId;
|
CPU_IDENTIFICATION CpuId;
|
||||||
KPROCESSOR_STATE ProcessorState;
|
KPROCESSOR_STATE ProcessorState;
|
||||||
|
KSPIN_LOCK PrcbLock;
|
||||||
KSPIN_LOCK_QUEUE LockQueue[MaximumLock];
|
KSPIN_LOCK_QUEUE LockQueue[MaximumLock];
|
||||||
ULONG_PTR MultiThreadProcessorSet;
|
ULONG_PTR MultiThreadProcessorSet;
|
||||||
|
VOLATILE ULONG IpiFrozen;
|
||||||
|
VOLATILE LONG_PTR RequestSummary;
|
||||||
KDPC_DATA DpcData[2];
|
KDPC_DATA DpcData[2];
|
||||||
PVOID DpcStack;
|
PVOID DpcStack;
|
||||||
|
LONG MaximumDpcQueueDepth;
|
||||||
|
ULONG DpcRequestRate;
|
||||||
|
BOOLEAN DpcInterruptRequested;
|
||||||
VOLATILE BOOLEAN DpcRoutineActive;
|
VOLATILE BOOLEAN DpcRoutineActive;
|
||||||
|
ULONG DpcLastCount;
|
||||||
|
VOLATILE ULONG_PTR TimerHand;
|
||||||
VOLATILE ULONG_PTR TimerRequest;
|
VOLATILE ULONG_PTR TimerRequest;
|
||||||
SINGLE_LIST_ENTRY DeferredReadyListHead;
|
SINGLE_LIST_ENTRY DeferredReadyListHead;
|
||||||
|
ULONG InterruptCount;
|
||||||
|
ULONG KernelTime;
|
||||||
|
ULONG UserTime;
|
||||||
|
ULONG DpcTime;
|
||||||
|
ULONG InterruptTime;
|
||||||
|
ULONG AdjustDpcThreshold;
|
||||||
PROCESSOR_POWER_STATE PowerState;
|
PROCESSOR_POWER_STATE PowerState;
|
||||||
ULONG ProfilingCountdown;
|
ULONG ProfilingCountdown;
|
||||||
} KPROCESSOR_CONTROL_BLOCK, *PKPROCESSOR_CONTROL_BLOCK;
|
} KPROCESSOR_CONTROL_BLOCK, *PKPROCESSOR_CONTROL_BLOCK;
|
||||||
|
|||||||
@@ -24,14 +24,30 @@
|
|||||||
/* Maximum number of exception parameters */
|
/* Maximum number of exception parameters */
|
||||||
#define EXCEPTION_MAXIMUM_PARAMETERS 15
|
#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 */
|
/* APC pending state length */
|
||||||
#define KAPC_STATE_LENGTH (FIELD_OFFSET(KAPC_STATE, UserApcPending) + sizeof(BOOLEAN))
|
#define KAPC_STATE_LENGTH (FIELD_OFFSET(KAPC_STATE, UserApcPending) + sizeof(BOOLEAN))
|
||||||
|
|
||||||
/* Kernel service descriptor tables count */
|
/* Kernel service descriptor tables count */
|
||||||
#define KSERVICE_TABLES_COUNT 4
|
#define KSERVICE_TABLES_COUNT 4
|
||||||
|
|
||||||
/* Timer length */
|
/* Timer related definitions */
|
||||||
#define KTIMER_LENGTH (FIELD_OFFSET(KTIMER, Period) + sizeof(LONG))
|
#define KTIMER_LENGTH (FIELD_OFFSET(KTIMER, Period) + sizeof(LONG))
|
||||||
|
#define KTIMER_TABLE_SIZE 512
|
||||||
|
|
||||||
/* Kernel builtin wait blocks */
|
/* Kernel builtin wait blocks */
|
||||||
#define EVENT_WAIT_BLOCK 2
|
#define EVENT_WAIT_BLOCK 2
|
||||||
@@ -79,6 +95,15 @@ typedef enum _KAPC_ENVIRONMENT
|
|||||||
InsertApcEnvironment
|
InsertApcEnvironment
|
||||||
} KAPC_ENVIRONMENT, *PKAPC_ENVIRONMENT;
|
} KAPC_ENVIRONMENT, *PKAPC_ENVIRONMENT;
|
||||||
|
|
||||||
|
/* Continue status enumeration list */
|
||||||
|
typedef enum _KCONTINUE_STATUS
|
||||||
|
{
|
||||||
|
ContinueError,
|
||||||
|
ContinueSuccess,
|
||||||
|
ContinueProcessorReselected,
|
||||||
|
ContinueNextProcessor
|
||||||
|
} KCONTINUE_STATUS, *PKCONTINUE_STATUS;
|
||||||
|
|
||||||
/* DPC importance enumeration list */
|
/* DPC importance enumeration list */
|
||||||
typedef enum _KDPC_IMPORTANCE
|
typedef enum _KDPC_IMPORTANCE
|
||||||
{
|
{
|
||||||
@@ -212,6 +237,55 @@ typedef enum _KTIMER_TYPE
|
|||||||
SynchronizationTimer
|
SynchronizationTimer
|
||||||
} KTIMER_TYPE, *PKTIMER_TYPE;
|
} 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 */
|
/* APC Types */
|
||||||
typedef enum _MODE
|
typedef enum _MODE
|
||||||
{
|
{
|
||||||
@@ -263,6 +337,15 @@ typedef struct _EXCEPTION_RECORD
|
|||||||
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
|
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
|
||||||
} EXCEPTION_RECORD, *PEXCEPTION_RECORD;
|
} 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 */
|
/* Asynchronous Procedure Call (APC) object structure definition */
|
||||||
typedef struct _KAPC
|
typedef struct _KAPC
|
||||||
{
|
{
|
||||||
@@ -419,7 +502,8 @@ typedef struct _KPROCESS
|
|||||||
ULONG_PTR DirectoryTable[2];
|
ULONG_PTR DirectoryTable[2];
|
||||||
USHORT IopmOffset;
|
USHORT IopmOffset;
|
||||||
UCHAR Iopl;
|
UCHAR Iopl;
|
||||||
VOLATILE KAFFINITY ActiveProcessors;
|
PKAFFINITY_MAP Affinity;
|
||||||
|
PKAFFINITY_MAP ActiveProcessors;
|
||||||
ULONG KernelTime;
|
ULONG KernelTime;
|
||||||
ULONG UserTime;
|
ULONG UserTime;
|
||||||
LIST_ENTRY ReadyListHead;
|
LIST_ENTRY ReadyListHead;
|
||||||
@@ -427,7 +511,6 @@ typedef struct _KPROCESS
|
|||||||
PVOID VdmTrapHandler;
|
PVOID VdmTrapHandler;
|
||||||
LIST_ENTRY ThreadListHead;
|
LIST_ENTRY ThreadListHead;
|
||||||
KSPIN_LOCK ProcessLock;
|
KSPIN_LOCK ProcessLock;
|
||||||
KAFFINITY Affinity;
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
@@ -482,7 +565,6 @@ typedef struct _KTHREAD
|
|||||||
PVOID StackBase;
|
PVOID StackBase;
|
||||||
PVOID StackLimit;
|
PVOID StackLimit;
|
||||||
KSPIN_LOCK ThreadLock;
|
KSPIN_LOCK ThreadLock;
|
||||||
|
|
||||||
ULONG ContextSwitches;
|
ULONG ContextSwitches;
|
||||||
VOLATILE UCHAR State;
|
VOLATILE UCHAR State;
|
||||||
UCHAR NpxState;
|
UCHAR NpxState;
|
||||||
@@ -507,7 +589,7 @@ typedef struct _KTHREAD
|
|||||||
PKWAIT_BLOCK WaitBlockList;
|
PKWAIT_BLOCK WaitBlockList;
|
||||||
BOOLEAN Alertable;
|
BOOLEAN Alertable;
|
||||||
BOOLEAN WaitNext;
|
BOOLEAN WaitNext;
|
||||||
UCHAR WaitReason;
|
KWAIT_REASON WaitReason;
|
||||||
SCHAR Priority;
|
SCHAR Priority;
|
||||||
UCHAR StackSwap;
|
UCHAR StackSwap;
|
||||||
VOLATILE UCHAR SwapBusy;
|
VOLATILE UCHAR SwapBusy;
|
||||||
@@ -545,9 +627,9 @@ typedef struct _KTHREAD
|
|||||||
CHAR PreviousMode;
|
CHAR PreviousMode;
|
||||||
UCHAR ResourceIndex;
|
UCHAR ResourceIndex;
|
||||||
UCHAR DisableBoost;
|
UCHAR DisableBoost;
|
||||||
KAFFINITY UserAffinity;
|
PKAFFINITY_MAP UserAffinity;
|
||||||
PKPROCESS Process;
|
PKPROCESS Process;
|
||||||
KAFFINITY Affinity;
|
PKAFFINITY_MAP Affinity;
|
||||||
PVOID ServiceTable;
|
PVOID ServiceTable;
|
||||||
PKAPC_STATE ApcStatePointer[2];
|
PKAPC_STATE ApcStatePointer[2];
|
||||||
KAPC_STATE SavedApcState;
|
KAPC_STATE SavedApcState;
|
||||||
@@ -563,7 +645,7 @@ typedef struct _KTHREAD
|
|||||||
LIST_ENTRY ThreadListEntry;
|
LIST_ENTRY ThreadListEntry;
|
||||||
UCHAR LargeStack;
|
UCHAR LargeStack;
|
||||||
UCHAR PowerState;
|
UCHAR PowerState;
|
||||||
UCHAR NpxIrql;
|
UCHAR NpxRunLevel;
|
||||||
UCHAR Spare5;
|
UCHAR Spare5;
|
||||||
BOOLEAN AutoAlignment;
|
BOOLEAN AutoAlignment;
|
||||||
UCHAR Iopl;
|
UCHAR Iopl;
|
||||||
|
|||||||
@@ -99,14 +99,20 @@ typedef struct _M128
|
|||||||
/* Dispatcher object header structure definition */
|
/* Dispatcher object header structure definition */
|
||||||
typedef struct _DISPATCHER_HEADER
|
typedef struct _DISPATCHER_HEADER
|
||||||
{
|
{
|
||||||
UCHAR Type;
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
UCHAR Type;
|
||||||
UCHAR Absolute;
|
UCHAR Absolute;
|
||||||
UCHAR NpxIrql;
|
UCHAR Size;
|
||||||
};
|
union {
|
||||||
UCHAR Inserted;
|
UCHAR Inserted;
|
||||||
BOOLEAN DebugActive;
|
BOOLEAN DebugActive;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
VOLATILE LONG Lock;
|
||||||
|
};
|
||||||
LONG SignalState;
|
LONG SignalState;
|
||||||
LIST_ENTRY WaitListHead;
|
LIST_ENTRY WaitListHead;
|
||||||
} DISPATCHER_HEADER, *PDISPATCHER_HEADER;
|
} DISPATCHER_HEADER, *PDISPATCHER_HEADER;
|
||||||
|
|||||||
@@ -48,6 +48,7 @@
|
|||||||
|
|
||||||
/* XT status code definitions */
|
/* XT status code definitions */
|
||||||
#define STATUS_SUCCESS ((XTSTATUS) 0x00000000L)
|
#define STATUS_SUCCESS ((XTSTATUS) 0x00000000L)
|
||||||
|
#define STATUS_WAKE_SYSTEM_DEBUGGER ((XTSTATUS) 0x80000007L)
|
||||||
#define STATUS_END_OF_MEDIA ((XTSTATUS) 0x8000001EL)
|
#define STATUS_END_OF_MEDIA ((XTSTATUS) 0x8000001EL)
|
||||||
#define STATUS_RESOURCE_LOCKED ((XTSTATUS) 0xC0000000L)
|
#define STATUS_RESOURCE_LOCKED ((XTSTATUS) 0xC0000000L)
|
||||||
#define STATUS_UNSUCCESSFUL ((XTSTATUS) 0xC0000001L)
|
#define STATUS_UNSUCCESSFUL ((XTSTATUS) 0xC0000001L)
|
||||||
@@ -59,6 +60,7 @@
|
|||||||
#define STATUS_INVALID_PARAMETER ((XTSTATUS) 0xC000000DL)
|
#define STATUS_INVALID_PARAMETER ((XTSTATUS) 0xC000000DL)
|
||||||
#define STATUS_END_OF_FILE ((XTSTATUS) 0xC0000011L)
|
#define STATUS_END_OF_FILE ((XTSTATUS) 0xC0000011L)
|
||||||
#define STATUS_NO_MEMORY ((XTSTATUS) 0xC0000017L)
|
#define STATUS_NO_MEMORY ((XTSTATUS) 0xC0000017L)
|
||||||
|
#define STATUS_BUFFER_TOO_SMALL ((XTSTATUS) 0xC0000023L)
|
||||||
#define STATUS_PORT_DISCONNECTED ((XTSTATUS) 0xC0000037L)
|
#define STATUS_PORT_DISCONNECTED ((XTSTATUS) 0xC0000037L)
|
||||||
#define STATUS_CRC_ERROR ((XTSTATUS) 0xC000003FL)
|
#define STATUS_CRC_ERROR ((XTSTATUS) 0xC000003FL)
|
||||||
#define STATUS_FLOAT_OVERFLOW ((XTSTATUS) 0xC0000091L)
|
#define STATUS_FLOAT_OVERFLOW ((XTSTATUS) 0xC0000091L)
|
||||||
|
|||||||
@@ -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 _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 _HAL_APIC_MODE HAL_APIC_MODE, *PHAL_APIC_MODE;
|
||||||
typedef enum _KAPC_ENVIRONMENT KAPC_ENVIRONMENT, *PKAPC_ENVIRONMENT;
|
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 _KDPC_IMPORTANCE KDPC_IMPORTANCE, *PKDPC_IMPORTANCE;
|
||||||
typedef enum _KEVENT_TYPE KEVENT_TYPE, *PKEVENT_TYPE;
|
typedef enum _KEVENT_TYPE KEVENT_TYPE, *PKEVENT_TYPE;
|
||||||
typedef enum _KOBJECTS KOBJECTS, *PKOBJECTS;
|
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 _KTHREAD_STATE KTHREAD_STATE, *PKTHREAD_STATE;
|
||||||
typedef enum _KTIMER_TYPE KTIMER_TYPE, *PKTIMER_TYPE;
|
typedef enum _KTIMER_TYPE KTIMER_TYPE, *PKTIMER_TYPE;
|
||||||
typedef enum _KUBSAN_DATA_TYPE KUBSAN_DATA_TYPE, *PKUBSAN_DATA_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 _LOADER_MEMORY_TYPE LOADER_MEMORY_TYPE, *PLOADER_MEMORY_TYPE;
|
||||||
typedef enum _MMPAGELISTS MMPAGELISTS, *PMMPAGELISTS;
|
typedef enum _MMPAGELISTS MMPAGELISTS, *PMMPAGELISTS;
|
||||||
typedef enum _MMPFN_CACHE_ATTRIBUTE MMPFN_CACHE_ATTRIBUTE, *PMMPFN_CACHE_ATTRIBUTE;
|
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 _GUID GUID, *PGUID;
|
||||||
typedef struct _HL_FRAMEBUFFER_DATA HL_FRAMEBUFFER_DATA, *PHL_FRAMEBUFFER_DATA;
|
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 _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 KAPC, *PKAPC;
|
||||||
typedef struct _KAPC_STATE KAPC_STATE, *PKAPC_STATE;
|
typedef struct _KAPC_STATE KAPC_STATE, *PKAPC_STATE;
|
||||||
typedef struct _KD_DEBUG_MODE KD_DEBUG_MODE, *PKD_DEBUG_MODE;
|
typedef struct _KD_DEBUG_MODE KD_DEBUG_MODE, *PKD_DEBUG_MODE;
|
||||||
|
|||||||
@@ -31,13 +31,16 @@ list(APPEND XTOSKRNL_SOURCE
|
|||||||
${XTOSKRNL_SOURCE_DIR}/hl/fbdev.cc
|
${XTOSKRNL_SOURCE_DIR}/hl/fbdev.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/hl/init.cc
|
${XTOSKRNL_SOURCE_DIR}/hl/init.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/hl/ioreg.cc
|
${XTOSKRNL_SOURCE_DIR}/hl/ioreg.cc
|
||||||
|
${XTOSKRNL_SOURCE_DIR}/kd/${ARCH}/debug.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/kd/data.cc
|
${XTOSKRNL_SOURCE_DIR}/kd/data.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/kd/dbgio.cc
|
${XTOSKRNL_SOURCE_DIR}/kd/dbgio.cc
|
||||||
|
${XTOSKRNL_SOURCE_DIR}/kd/debug.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/kd/exports.cc
|
${XTOSKRNL_SOURCE_DIR}/kd/exports.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/ke/${ARCH}/dispatch.cc
|
${XTOSKRNL_SOURCE_DIR}/ke/${ARCH}/dispatch.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/ke/${ARCH}/krnlinit.cc
|
${XTOSKRNL_SOURCE_DIR}/ke/${ARCH}/krnlinit.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/ke/${ARCH}/kthread.cc
|
${XTOSKRNL_SOURCE_DIR}/ke/${ARCH}/kthread.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/ke/${ARCH}/proc.cc
|
${XTOSKRNL_SOURCE_DIR}/ke/${ARCH}/proc.cc
|
||||||
|
${XTOSKRNL_SOURCE_DIR}/ke/affinity.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/ke/apc.cc
|
${XTOSKRNL_SOURCE_DIR}/ke/apc.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/ke/bootinfo.cc
|
${XTOSKRNL_SOURCE_DIR}/ke/bootinfo.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/ke/crash.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/dpc.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/ke/event.cc
|
${XTOSKRNL_SOURCE_DIR}/ke/event.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/ke/exports.cc
|
${XTOSKRNL_SOURCE_DIR}/ke/exports.cc
|
||||||
|
${XTOSKRNL_SOURCE_DIR}/ke/ipi.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/ke/kprocess.cc
|
${XTOSKRNL_SOURCE_DIR}/ke/kprocess.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/ke/krnlinit.cc
|
${XTOSKRNL_SOURCE_DIR}/ke/krnlinit.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/ke/kthread.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/shdata.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/ke/spinlock.cc
|
${XTOSKRNL_SOURCE_DIR}/ke/spinlock.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/ke/sysres.cc
|
${XTOSKRNL_SOURCE_DIR}/ke/sysres.cc
|
||||||
|
${XTOSKRNL_SOURCE_DIR}/ke/sysserv.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/ke/systime.cc
|
${XTOSKRNL_SOURCE_DIR}/ke/systime.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/ke/timer.cc
|
${XTOSKRNL_SOURCE_DIR}/ke/timer.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/mm/${ARCH}/mmgr.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/pool.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/mm/pte.cc
|
${XTOSKRNL_SOURCE_DIR}/mm/pte.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/po/idle.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}/dispatch.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/rtl/${ARCH}/exsup.cc
|
${XTOSKRNL_SOURCE_DIR}/rtl/${ARCH}/exsup.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/rtl/${ARCH}/intrin.cc
|
${XTOSKRNL_SOURCE_DIR}/rtl/${ARCH}/intrin.cc
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ corresponding C++ namespace in which the subsystem's classes and routines reside
|
|||||||
* Ke - Core Kernel Library
|
* Ke - Core Kernel Library
|
||||||
* Mm - Memory Manager
|
* Mm - Memory Manager
|
||||||
* Po - Plug&Play and Power Manager
|
* Po - Plug&Play and Power Manager
|
||||||
|
* Ps - Process and Thread Manager
|
||||||
* Rtl - Runtime library
|
* Rtl - Runtime library
|
||||||
|
|
||||||
### AR: Architecture 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
|
supporting device detection and installation at boot time. Furthermore, it is responsible for starting and stopping
|
||||||
devices on demand.
|
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
|
### RTL: Runtime Library
|
||||||
The Runtime Library provides a kernel-mode implementation of common C library functions. It includes many utility
|
The Runtime Library provides a kernel-mode implementation of common C library functions. It includes many utility
|
||||||
routines, for use by other kernel components.
|
routines, for use by other kernel components.
|
||||||
|
|||||||
@@ -617,6 +617,56 @@ AR::CpuFunctions::ReadWriteBarrier(VOID)
|
|||||||
: "memory");
|
: "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.
|
* Instructs the processor to set the interrupt flag.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ XTAPI
|
|||||||
VOID
|
VOID
|
||||||
AR::ProcessorSupport::GetTrampolineInformation(IN TRAMPOLINE_TYPE TrampolineType,
|
AR::ProcessorSupport::GetTrampolineInformation(IN TRAMPOLINE_TYPE TrampolineType,
|
||||||
OUT PVOID *TrampolineCode,
|
OUT PVOID *TrampolineCode,
|
||||||
OUT PULONG_PTR TrampolineSize)
|
OUT PULONG TrampolineSize)
|
||||||
{
|
{
|
||||||
/* Get trampoline information */
|
/* Get trampoline information */
|
||||||
switch(TrampolineType)
|
switch(TrampolineType)
|
||||||
@@ -320,30 +320,28 @@ AR::ProcessorSupport::InitializeIdt(IN PKPROCESSOR_BLOCK ProcessorBlock)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Setup IDT handlers for known interrupts and traps */
|
/* 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, 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_TRAP_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, 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, 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_TRAP_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_TRAP_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_TRAP_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_TRAP_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_TRAP_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_TRAP_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_TRAP_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_TRAP_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_TRAP_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_TRAP_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_TRAP_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_TRAP_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_TRAP_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_TRAP_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_TRAP_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, 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, 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_TRAP_GATE);
|
SetIdtGate(ProcessorBlock->IdtBase, 0x2D, (PVOID)ArTrapEntry[0x2D], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING3, AMD64_INTERRUPT_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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -477,8 +475,9 @@ AR::ProcessorSupport::InitializeProcessorBlock(OUT PKPROCESSOR_BLOCK ProcessorBl
|
|||||||
/* Set initial MXCSR register value */
|
/* Set initial MXCSR register value */
|
||||||
ProcessorBlock->Prcb.MxCsr = INITIAL_MXCSR;
|
ProcessorBlock->Prcb.MxCsr = INITIAL_MXCSR;
|
||||||
|
|
||||||
/* Set initial runlevel */
|
/* Set initial runlevel and mark processor as started */
|
||||||
ProcessorBlock->RunLevel = PASSIVE_LEVEL;
|
ProcessorBlock->RunLevel = PASSIVE_LEVEL;
|
||||||
|
ProcessorBlock->Started = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -171,14 +171,6 @@ AR::Traps::DispatchTrap(IN PKTRAP_FRAME TrapFrame)
|
|||||||
/* Debug-Service-Request raised */
|
/* Debug-Service-Request raised */
|
||||||
HandleTrap2D(TrapFrame);
|
HandleTrap2D(TrapFrame);
|
||||||
break;
|
break;
|
||||||
case 0x2F:
|
|
||||||
/* Software Interrupt at DISPATCH level */
|
|
||||||
HandleTrap2F(TrapFrame);
|
|
||||||
break;
|
|
||||||
case 0xE1:
|
|
||||||
/* InterProcessor Interrupt (IPI) */
|
|
||||||
HandleTrapE1(TrapFrame);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
/* Unknown/Unexpected trap */
|
/* Unknown/Unexpected trap */
|
||||||
HandleTrapFF(TrapFrame);
|
HandleTrapFF(TrapFrame);
|
||||||
@@ -608,40 +600,6 @@ AR::Traps::HandleTrap2D(IN PKTRAP_FRAME TrapFrame)
|
|||||||
KE::Crash::Panic(0x2D);
|
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.
|
* Handles the trap 0xFF when Unexpected Interrupt occurs.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -587,6 +587,56 @@ AR::CpuFunctions::ReadWriteBarrier(VOID)
|
|||||||
: "memory");
|
: "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.
|
* Instructs the processor to set the interrupt flag.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ XTAPI
|
|||||||
VOID
|
VOID
|
||||||
AR::ProcessorSupport::GetTrampolineInformation(IN TRAMPOLINE_TYPE TrampolineType,
|
AR::ProcessorSupport::GetTrampolineInformation(IN TRAMPOLINE_TYPE TrampolineType,
|
||||||
OUT PVOID *TrampolineCode,
|
OUT PVOID *TrampolineCode,
|
||||||
OUT PULONG_PTR TrampolineSize)
|
OUT PULONG TrampolineSize)
|
||||||
{
|
{
|
||||||
/* Get trampoline information */
|
/* Get trampoline information */
|
||||||
switch(TrampolineType)
|
switch(TrampolineType)
|
||||||
@@ -465,8 +465,9 @@ AR::ProcessorSupport::InitializeProcessorBlock(OUT PKPROCESSOR_BLOCK ProcessorBl
|
|||||||
ProcessorBlock->Prcb.IdleThread = &(KE::KThread::GetInitialThread())->ThreadControlBlock;
|
ProcessorBlock->Prcb.IdleThread = &(KE::KThread::GetInitialThread())->ThreadControlBlock;
|
||||||
ProcessorBlock->Prcb.NextThread = NULLPTR;
|
ProcessorBlock->Prcb.NextThread = NULLPTR;
|
||||||
|
|
||||||
/* Set initial runlevel */
|
/* Set initial runlevel and mark processor as started */
|
||||||
ProcessorBlock->RunLevel = PASSIVE_LEVEL;
|
ProcessorBlock->RunLevel = PASSIVE_LEVEL;
|
||||||
|
ProcessorBlock->Started = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ ACPI_SYSTEM_INFO HL::Acpi::SystemInfo;
|
|||||||
ACPI_TIMER_INFO HL::Acpi::TimerInfo;
|
ACPI_TIMER_INFO HL::Acpi::TimerInfo;
|
||||||
|
|
||||||
/* Represents the number of active processors */
|
/* Represents the number of active processors */
|
||||||
KAFFINITY HL::Cpu::ActiveProcessors;
|
PKAFFINITY_MAP HL::Cpu::ActiveProcessors;
|
||||||
|
|
||||||
/* Metadata detailing the linear frame buffer geometry */
|
/* Metadata detailing the linear frame buffer geometry */
|
||||||
HL_FRAMEBUFFER_DATA HL::FrameBuffer::FrameBufferData;
|
HL_FRAMEBUFFER_DATA HL::FrameBuffer::FrameBufferData;
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ VOID
|
|||||||
HL::Cpu::InitializeProcessor(VOID)
|
HL::Cpu::InitializeProcessor(VOID)
|
||||||
{
|
{
|
||||||
PKPROCESSOR_BLOCK ProcessorBlock;
|
PKPROCESSOR_BLOCK ProcessorBlock;
|
||||||
KAFFINITY Affinity;
|
|
||||||
|
|
||||||
/* Get current processor block */
|
/* Get current processor block */
|
||||||
ProcessorBlock = KE::Processor::GetCurrentProcessorBlock();
|
ProcessorBlock = KE::Processor::GetCurrentProcessorBlock();
|
||||||
@@ -33,17 +32,46 @@ HL::Cpu::InitializeProcessor(VOID)
|
|||||||
ProcessorBlock->StallScaleFactor = INITIAL_STALL_FACTOR;
|
ProcessorBlock->StallScaleFactor = INITIAL_STALL_FACTOR;
|
||||||
ProcessorBlock->Idr = 0xFFFFFFFF;
|
ProcessorBlock->Idr = 0xFFFFFFFF;
|
||||||
|
|
||||||
/* Set processor affinity */
|
/* Check if active processors map is initialized */
|
||||||
Affinity = (KAFFINITY) 1 << ProcessorBlock->CpuNumber;
|
if(ActiveProcessors != NULLPTR)
|
||||||
|
{
|
||||||
/* Apply affinity to a set of processors */
|
/* Register this CPU in the global active processors map */
|
||||||
ActiveProcessors |= Affinity;
|
KE::Affinity::AtomicSetProcessorAffinity(ActiveProcessors, ProcessorBlock->CpuNumber);
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialize APIC for this processor */
|
/* Initialize APIC for this processor */
|
||||||
HL::Pic::InitializePic();
|
HL::Pic::InitializePic();
|
||||||
|
|
||||||
/* Set the APIC running level */
|
/* 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
|
XTSTATUS
|
||||||
HL::Cpu::StartAllProcessors(VOID)
|
HL::Cpu::StartAllProcessors(VOID)
|
||||||
{
|
{
|
||||||
ULONG CpuNumber, Index, MaxCpus, SipiVector, Timeout, TrampolinePages;
|
ULONG ApPages, CpuNumber, Index, MaxCpus, SipiVector, Timeout, TrampolineCodeSize;
|
||||||
PVOID CpuStructures, TrampolineAddress, TrampolineCode;
|
PVOID ApVirtualAddress, CpuStructures, TrampolineCode;
|
||||||
ULONG_PTR AllocationSize, TrampolineCodeSize;
|
PHYSICAL_ADDRESS ApPhysicalAddress;
|
||||||
PPROCESSOR_START_BLOCK StartBlock;
|
PPROCESSOR_START_BLOCK StartBlock;
|
||||||
PKPROCESSOR_BLOCK ProcessorBlock;
|
PKPROCESSOR_BLOCK ProcessorBlock;
|
||||||
PACPI_SYSTEM_INFO SysInfo;
|
PACPI_SYSTEM_INFO SysInfo;
|
||||||
@@ -108,27 +136,34 @@ HL::Cpu::StartAllProcessors(VOID)
|
|||||||
return STATUS_UNSUCCESSFUL;
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compute trampoline memory allocation size (trampoline + processor start block + temporary stack) */
|
/* Allocate low memory for AP trampoline code */
|
||||||
AllocationSize = TrampolineCodeSize + sizeof(PROCESSOR_START_BLOCK) + 512;
|
Status = MM::HardwarePool::AllocateLowMemory(&ApPhysicalAddress, &ApVirtualAddress);
|
||||||
TrampolinePages = (ULONG)(ROUND_UP(AllocationSize, MM_PAGE_SIZE) / MM_PAGE_SIZE);
|
|
||||||
|
|
||||||
/* Allocate real mode memory for AP trampoline */
|
|
||||||
Status = MM::HardwarePool::AllocateRealModeMemory(TrampolinePages, &TrampolineAddress);
|
|
||||||
if(Status != STATUS_SUCCESS)
|
if(Status != STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
/* Failed to allocate memory, print error message and return error */
|
/* 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;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy trampoline code to low memory */
|
/* 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 */
|
/* 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 */
|
/* Get SIPI vector */
|
||||||
SipiVector = (ULONG)((ULONG_PTR)TrampolineAddress >> 12);
|
SipiVector = (ULONG)(ApPhysicalAddress.QuadPart >> APIC_VECTOR_SIPI_SHIFT);
|
||||||
|
|
||||||
/* Loop over all CPUs */
|
/* Loop over all CPUs */
|
||||||
CpuNumber = 0;
|
CpuNumber = 0;
|
||||||
@@ -155,8 +190,8 @@ HL::Cpu::StartAllProcessors(VOID)
|
|||||||
Status = MM::KernelPool::AllocateProcessorStructures(&CpuStructures);
|
Status = MM::KernelPool::AllocateProcessorStructures(&CpuStructures);
|
||||||
if(Status != STATUS_SUCCESS)
|
if(Status != STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
/* Failed to allocate memory, unmap memory and return error */
|
/* Failed to allocate memory, unmap temporary identity mapping and return error */
|
||||||
MM::HardwarePool::UnmapHardwareMemory(TrampolineAddress, TrampolinePages, TRUE);
|
MM::HardwarePool::UnmapRealModeMemory(ApPhysicalAddress, ApPages);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,7 +249,7 @@ HL::Cpu::StartAllProcessors(VOID)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unmap trampoline memory and return success */
|
/* Unmap temporary identity mapping and return success */
|
||||||
MM::HardwarePool::UnmapHardwareMemory(TrampolineAddress, TrampolinePages, TRUE);
|
MM::HardwarePool::UnmapRealModeMemory(ApPhysicalAddress, ApPages);
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,10 @@ namespace AR
|
|||||||
STATIC XTCDECL ULONGLONG ReadTimeStampCounter(VOID);
|
STATIC XTCDECL ULONGLONG ReadTimeStampCounter(VOID);
|
||||||
STATIC XTCDECL ULONGLONG ReadTimeStampCounterProcessor(OUT PULONG TscAux);
|
STATIC XTCDECL ULONGLONG ReadTimeStampCounterProcessor(OUT PULONG TscAux);
|
||||||
STATIC XTCDECL VOID ReadWriteBarrier(VOID);
|
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 SetInterruptFlag(VOID);
|
||||||
STATIC XTCDECL VOID StoreGlobalDescriptorTable(OUT PVOID Destination);
|
STATIC XTCDECL VOID StoreGlobalDescriptorTable(OUT PVOID Destination);
|
||||||
STATIC XTCDECL VOID StoreInterruptDescriptorTable(OUT PVOID Destination);
|
STATIC XTCDECL VOID StoreInterruptDescriptorTable(OUT PVOID Destination);
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ namespace AR
|
|||||||
STATIC XTAPI PVOID GetBootStack(VOID);
|
STATIC XTAPI PVOID GetBootStack(VOID);
|
||||||
STATIC XTAPI VOID GetTrampolineInformation(IN TRAMPOLINE_TYPE TrampolineType,
|
STATIC XTAPI VOID GetTrampolineInformation(IN TRAMPOLINE_TYPE TrampolineType,
|
||||||
OUT PVOID *TrampolineCode,
|
OUT PVOID *TrampolineCode,
|
||||||
OUT PULONG_PTR TrampolineSize);
|
OUT PULONG TrampolineSize);
|
||||||
STATIC XTAPI VOID InitializeProcessor(IN PVOID ProcessorStructures);
|
STATIC XTAPI VOID InitializeProcessor(IN PVOID ProcessorStructures);
|
||||||
STATIC XTAPI VOID InitializeProcessorStructures(IN PVOID ProcessorStructures,
|
STATIC XTAPI VOID InitializeProcessorStructures(IN PVOID ProcessorStructures,
|
||||||
OUT PKGDTENTRY *Gdt,
|
OUT PKGDTENTRY *Gdt,
|
||||||
|
|||||||
@@ -51,8 +51,6 @@ namespace AR
|
|||||||
STATIC XTCDECL VOID HandleTrap1F(IN PKTRAP_FRAME TrapFrame);
|
STATIC XTCDECL VOID HandleTrap1F(IN PKTRAP_FRAME TrapFrame);
|
||||||
STATIC XTCDECL VOID HandleTrap2C(IN PKTRAP_FRAME TrapFrame);
|
STATIC XTCDECL VOID HandleTrap2C(IN PKTRAP_FRAME TrapFrame);
|
||||||
STATIC XTCDECL VOID HandleTrap2D(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);
|
STATIC XTCDECL VOID HandleTrapFF(IN PKTRAP_FRAME TrapFrame);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,10 @@ namespace AR
|
|||||||
STATIC XTCDECL ULONGLONG ReadTimeStampCounter(VOID);
|
STATIC XTCDECL ULONGLONG ReadTimeStampCounter(VOID);
|
||||||
STATIC XTCDECL ULONGLONG ReadTimeStampCounterProcessor(OUT PULONG TscAux);
|
STATIC XTCDECL ULONGLONG ReadTimeStampCounterProcessor(OUT PULONG TscAux);
|
||||||
STATIC XTCDECL VOID ReadWriteBarrier(VOID);
|
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 SetInterruptFlag(VOID);
|
||||||
STATIC XTCDECL VOID StoreGlobalDescriptorTable(OUT PVOID Destination);
|
STATIC XTCDECL VOID StoreGlobalDescriptorTable(OUT PVOID Destination);
|
||||||
STATIC XTCDECL VOID StoreInterruptDescriptorTable(OUT PVOID Destination);
|
STATIC XTCDECL VOID StoreInterruptDescriptorTable(OUT PVOID Destination);
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ namespace AR
|
|||||||
STATIC XTAPI PVOID GetBootStack(VOID);
|
STATIC XTAPI PVOID GetBootStack(VOID);
|
||||||
STATIC XTAPI VOID GetTrampolineInformation(IN TRAMPOLINE_TYPE TrampolineType,
|
STATIC XTAPI VOID GetTrampolineInformation(IN TRAMPOLINE_TYPE TrampolineType,
|
||||||
OUT PVOID *TrampolineCode,
|
OUT PVOID *TrampolineCode,
|
||||||
OUT PULONG_PTR TrampolineSize);
|
OUT PULONG TrampolineSize);
|
||||||
STATIC XTAPI VOID InitializeProcessor(IN PVOID ProcessorStructures);
|
STATIC XTAPI VOID InitializeProcessor(IN PVOID ProcessorStructures);
|
||||||
STATIC XTAPI VOID InitializeProcessorStructures(IN PVOID ProcessorStructures,
|
STATIC XTAPI VOID InitializeProcessorStructures(IN PVOID ProcessorStructures,
|
||||||
OUT PKGDTENTRY *Gdt,
|
OUT PKGDTENTRY *Gdt,
|
||||||
|
|||||||
@@ -18,10 +18,11 @@ namespace HL
|
|||||||
class Cpu
|
class Cpu
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
STATIC KAFFINITY ActiveProcessors;
|
STATIC PKAFFINITY_MAP ActiveProcessors;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
STATIC XTAPI VOID InitializeProcessor(VOID);
|
STATIC XTAPI VOID InitializeProcessor(VOID);
|
||||||
|
STATIC XTAPI XTSTATUS InitializeProcessorAffinity(VOID);
|
||||||
STATIC XTAPI XTSTATUS StartAllProcessors(VOID);
|
STATIC XTAPI XTSTATUS StartAllProcessors(VOID);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,5 +13,6 @@
|
|||||||
|
|
||||||
#include <kd/dbg.hh>
|
#include <kd/dbg.hh>
|
||||||
#include <kd/dbgio.hh>
|
#include <kd/dbgio.hh>
|
||||||
|
#include <kd/debug.hh>
|
||||||
|
|
||||||
#endif /* __XTOSKRNL_KD_HH */
|
#endif /* __XTOSKRNL_KD_HH */
|
||||||
|
|||||||
38
xtoskrnl/includes/kd/debug.hh
Normal file
38
xtoskrnl/includes/kd/debug.hh
Normal 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 */
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include <xtos.hh>
|
#include <xtos.hh>
|
||||||
|
|
||||||
|
#include <ke/affinity.hh>
|
||||||
#include <ke/apc.hh>
|
#include <ke/apc.hh>
|
||||||
#include <ke/bootinfo.hh>
|
#include <ke/bootinfo.hh>
|
||||||
#include <ke/crash.hh>
|
#include <ke/crash.hh>
|
||||||
@@ -18,6 +19,7 @@
|
|||||||
#include <ke/dpc.hh>
|
#include <ke/dpc.hh>
|
||||||
#include <ke/event.hh>
|
#include <ke/event.hh>
|
||||||
#include <ke/guard.hh>
|
#include <ke/guard.hh>
|
||||||
|
#include <ke/ipi.hh>
|
||||||
#include <ke/kprocess.hh>
|
#include <ke/kprocess.hh>
|
||||||
#include <ke/krnlinit.hh>
|
#include <ke/krnlinit.hh>
|
||||||
#include <ke/kthread.hh>
|
#include <ke/kthread.hh>
|
||||||
@@ -28,6 +30,7 @@
|
|||||||
#include <ke/shdata.hh>
|
#include <ke/shdata.hh>
|
||||||
#include <ke/spinlock.hh>
|
#include <ke/spinlock.hh>
|
||||||
#include <ke/sysres.hh>
|
#include <ke/sysres.hh>
|
||||||
|
#include <ke/sysserv.hh>
|
||||||
#include <ke/systime.hh>
|
#include <ke/systime.hh>
|
||||||
#include <ke/timer.hh>
|
#include <ke/timer.hh>
|
||||||
|
|
||||||
|
|||||||
49
xtoskrnl/includes/ke/affinity.hh
Normal file
49
xtoskrnl/includes/ke/affinity.hh
Normal 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 */
|
||||||
@@ -17,7 +17,16 @@ namespace KE
|
|||||||
{
|
{
|
||||||
class Crash
|
class Crash
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
STATIC PKPROCESSOR_CONTROL_BLOCK FreezeOwner;
|
||||||
|
STATIC BOOLEAN KernelPanic;
|
||||||
|
STATIC KRUNLEVEL RunLevel;
|
||||||
|
|
||||||
public:
|
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 HaltSystem(VOID);
|
||||||
STATIC XTAPI VOID Panic(IN ULONG Code);
|
STATIC XTAPI VOID Panic(IN ULONG Code);
|
||||||
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 Parameter2,
|
||||||
IN ULONG_PTR Parameter3,
|
IN ULONG_PTR Parameter3,
|
||||||
IN ULONG_PTR Parameter4);
|
IN ULONG_PTR Parameter4);
|
||||||
|
STATIC XTAPI BOOLEAN SystemCrashed(VOID);
|
||||||
|
STATIC XTAPI VOID ThawExecution(IN BOOLEAN Interrupts);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ namespace KE
|
|||||||
class Dispatcher
|
class Dispatcher
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
STATIC XTAPI VOID EnterIdleLoop(VOID);
|
||||||
STATIC XTFASTCALL VOID ExitDispatcher(IN KRUNLEVEL OldRunLevel);
|
STATIC XTFASTCALL VOID ExitDispatcher(IN KRUNLEVEL OldRunLevel);
|
||||||
|
STATIC XTCDECL VOID HandleDispatchInterrupt(IN PKTRAP_FRAME TrapFrame);
|
||||||
STATIC XTFASTCALL BOOLEAN SwitchContext(IN PKTHREAD CurrentThread,
|
STATIC XTFASTCALL BOOLEAN SwitchContext(IN PKTHREAD CurrentThread,
|
||||||
IN KRUNLEVEL RunLevel);
|
IN KRUNLEVEL RunLevel);
|
||||||
STATIC XTAPI VOID UpdateRunTime(IN PKTRAP_FRAME TrapFrame,
|
STATIC XTAPI VOID UpdateRunTime(IN PKTRAP_FRAME TrapFrame,
|
||||||
|
|||||||
@@ -19,18 +19,27 @@ namespace KE
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
KSPIN_LOCK_QUEUE_LEVEL QueuedLockLevel;
|
KSPIN_LOCK_QUEUE_LEVEL QueuedLockLevel;
|
||||||
|
BOOLEAN Owned;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QueuedSpinLockGuard(IN OUT KSPIN_LOCK_QUEUE_LEVEL LockLevel)
|
QueuedSpinLockGuard(IN OUT KSPIN_LOCK_QUEUE_LEVEL LockLevel,
|
||||||
|
IN BOOLEAN Acquire = TRUE)
|
||||||
{
|
{
|
||||||
QueuedLockLevel = LockLevel;
|
QueuedLockLevel = LockLevel;
|
||||||
|
Owned = Acquire;
|
||||||
|
if(Owned)
|
||||||
|
{
|
||||||
KE::SpinLock::AcquireQueuedSpinLock(QueuedLockLevel);
|
KE::SpinLock::AcquireQueuedSpinLock(QueuedLockLevel);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
~QueuedSpinLockGuard()
|
~QueuedSpinLockGuard()
|
||||||
|
{
|
||||||
|
if(Owned)
|
||||||
{
|
{
|
||||||
KE::SpinLock::ReleaseQueuedSpinLock(QueuedLockLevel);
|
KE::SpinLock::ReleaseQueuedSpinLock(QueuedLockLevel);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QueuedSpinLockGuard(const QueuedSpinLockGuard&) = delete;
|
QueuedSpinLockGuard(const QueuedSpinLockGuard&) = delete;
|
||||||
QueuedSpinLockGuard& operator=(const QueuedSpinLockGuard&) = delete;
|
QueuedSpinLockGuard& operator=(const QueuedSpinLockGuard&) = delete;
|
||||||
@@ -40,18 +49,27 @@ namespace KE
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
PKSPIN_LOCK Lock;
|
PKSPIN_LOCK Lock;
|
||||||
|
BOOLEAN Owned;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SpinLockGuard(IN OUT PKSPIN_LOCK SpinLock)
|
SpinLockGuard(IN OUT PKSPIN_LOCK SpinLock,
|
||||||
|
IN BOOLEAN Acquire = TRUE)
|
||||||
{
|
{
|
||||||
Lock = SpinLock;
|
Lock = SpinLock;
|
||||||
|
Owned = Acquire;
|
||||||
|
if(Owned)
|
||||||
|
{
|
||||||
KE::SpinLock::AcquireSpinLock(Lock);
|
KE::SpinLock::AcquireSpinLock(Lock);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
~SpinLockGuard()
|
~SpinLockGuard()
|
||||||
|
{
|
||||||
|
if(Owned)
|
||||||
{
|
{
|
||||||
KE::SpinLock::ReleaseSpinLock(Lock);
|
KE::SpinLock::ReleaseSpinLock(Lock);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SpinLockGuard(const SpinLockGuard&) = delete;
|
SpinLockGuard(const SpinLockGuard&) = delete;
|
||||||
SpinLockGuard& operator=(const SpinLockGuard&) = delete;
|
SpinLockGuard& operator=(const SpinLockGuard&) = delete;
|
||||||
|
|||||||
31
xtoskrnl/includes/ke/ipi.hh
Normal file
31
xtoskrnl/includes/ke/ipi.hh
Normal 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 */
|
||||||
@@ -21,10 +21,13 @@ namespace KE
|
|||||||
STATIC EPROCESS InitialProcess;
|
STATIC EPROCESS InitialProcess;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
STATIC XTAPI PKPROCESS GetIdleProcess(VOID);
|
||||||
STATIC XTAPI PEPROCESS GetInitialProcess(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,
|
STATIC XTAPI VOID InitializeProcess(IN OUT PKPROCESS Process,
|
||||||
IN KPRIORITY Priority,
|
IN KPRIORITY Priority,
|
||||||
IN KAFFINITY Affinity,
|
IN PKAFFINITY_MAP AffinityMap,
|
||||||
IN PULONG_PTR DirectoryTable,
|
IN PULONG_PTR DirectoryTable,
|
||||||
IN BOOLEAN Alignment);
|
IN BOOLEAN Alignment);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ namespace KE
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
STATIC XTAPI VOID BootstrapKernel(VOID);
|
STATIC XTAPI VOID BootstrapKernel(VOID);
|
||||||
|
STATIC XTAPI VOID InitializeInterruptHandlers(VOID);
|
||||||
STATIC XTAPI VOID InitializeKernel(VOID);
|
STATIC XTAPI VOID InitializeKernel(VOID);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,10 @@ namespace KE
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
STATIC XTAPI PETHREAD GetInitialThread(VOID);
|
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,
|
STATIC XTAPI XTSTATUS InitializeThread(IN PKPROCESS Process,
|
||||||
IN OUT PKTHREAD Thread,
|
IN OUT PKTHREAD Thread,
|
||||||
IN PKSYSTEM_ROUTINE SystemRoutine,
|
IN PKSYSTEM_ROUTINE SystemRoutine,
|
||||||
|
|||||||
@@ -26,12 +26,25 @@ namespace KE
|
|||||||
STATIC XTAPI PKPROCESSOR_CONTROL_BLOCK GetCurrentProcessorControlBlock(VOID);
|
STATIC XTAPI PKPROCESSOR_CONTROL_BLOCK GetCurrentProcessorControlBlock(VOID);
|
||||||
STATIC XTAPI ULONG GetCurrentProcessorNumber(VOID);
|
STATIC XTAPI ULONG GetCurrentProcessorNumber(VOID);
|
||||||
STATIC XTAPI PKTHREAD GetCurrentThread(VOID);
|
STATIC XTAPI PKTHREAD GetCurrentThread(VOID);
|
||||||
|
STATIC XTAPI ULONG GetInstalledCpus(VOID);
|
||||||
STATIC XTAPI PKPROCESSOR_BLOCK GetProcessorBlock(IN ULONG CpuNumber);
|
STATIC XTAPI PKPROCESSOR_BLOCK GetProcessorBlock(IN ULONG CpuNumber);
|
||||||
STATIC XTAPI XTSTATUS InitializeProcessorBlocks();
|
STATIC XTAPI XTSTATUS InitializeProcessorBlocks();
|
||||||
STATIC XTAPI VOID RegisterHardwareId(IN ULONG HardwareId);
|
STATIC XTAPI VOID RegisterHardwareId(IN ULONG HardwareId);
|
||||||
STATIC XTAPI VOID RegisterProcessorBlock(ULONG CpuNumber,
|
STATIC XTAPI VOID RegisterProcessorBlock(ULONG CpuNumber,
|
||||||
PKPROCESSOR_BLOCK ProcessorBlock);
|
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);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,18 +27,27 @@ namespace KE
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
KRUNLEVEL PreviousRunLevel;
|
KRUNLEVEL PreviousRunLevel;
|
||||||
|
BOOLEAN Switched;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LowerRunLevel(KRUNLEVEL RunLevel)
|
LowerRunLevel(IN KRUNLEVEL RunLevel,
|
||||||
|
IN BOOLEAN ChangeLevel = TRUE)
|
||||||
{
|
{
|
||||||
PreviousRunLevel = KE::RunLevel::GetCurrentRunLevel();
|
PreviousRunLevel = KE::RunLevel::GetCurrentRunLevel();
|
||||||
|
Switched = ChangeLevel;
|
||||||
|
if(Switched)
|
||||||
|
{
|
||||||
KE::RunLevel::LowerRunLevel(RunLevel);
|
KE::RunLevel::LowerRunLevel(RunLevel);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
~LowerRunLevel()
|
~LowerRunLevel()
|
||||||
|
{
|
||||||
|
if(Switched)
|
||||||
{
|
{
|
||||||
KE::RunLevel::RaiseRunLevel(PreviousRunLevel);
|
KE::RunLevel::RaiseRunLevel(PreviousRunLevel);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LowerRunLevel(const LowerRunLevel&) = delete;
|
LowerRunLevel(const LowerRunLevel&) = delete;
|
||||||
LowerRunLevel& operator=(const LowerRunLevel&) = delete;
|
LowerRunLevel& operator=(const LowerRunLevel&) = delete;
|
||||||
@@ -48,18 +57,27 @@ namespace KE
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
KRUNLEVEL PreviousRunLevel;
|
KRUNLEVEL PreviousRunLevel;
|
||||||
|
BOOLEAN Switched;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RaiseRunLevel(KRUNLEVEL RunLevel)
|
RaiseRunLevel(IN KRUNLEVEL RunLevel,
|
||||||
|
IN BOOLEAN ChangeLevel = TRUE)
|
||||||
{
|
{
|
||||||
PreviousRunLevel = KE::RunLevel::GetCurrentRunLevel();
|
PreviousRunLevel = KE::RunLevel::GetCurrentRunLevel();
|
||||||
|
Switched = ChangeLevel;
|
||||||
|
if(Switched)
|
||||||
|
{
|
||||||
KE::RunLevel::RaiseRunLevel(RunLevel);
|
KE::RunLevel::RaiseRunLevel(RunLevel);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
~RaiseRunLevel()
|
~RaiseRunLevel()
|
||||||
|
{
|
||||||
|
if(Switched)
|
||||||
{
|
{
|
||||||
KE::RunLevel::LowerRunLevel(PreviousRunLevel);
|
KE::RunLevel::LowerRunLevel(PreviousRunLevel);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RaiseRunLevel(const RaiseRunLevel&) = delete;
|
RaiseRunLevel(const RaiseRunLevel&) = delete;
|
||||||
RaiseRunLevel& operator=(const RaiseRunLevel&) = delete;
|
RaiseRunLevel& operator=(const RaiseRunLevel&) = delete;
|
||||||
|
|||||||
25
xtoskrnl/includes/ke/sysserv.hh
Normal file
25
xtoskrnl/includes/ke/sysserv.hh
Normal 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 */
|
||||||
@@ -17,6 +17,9 @@ namespace KE
|
|||||||
{
|
{
|
||||||
class Timer
|
class Timer
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
STATIC LIST_ENTRY TimerTableListHead[KTIMER_TABLE_SIZE];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
STATIC XTAPI BOOLEAN CancelTimer(IN PKTIMER Timer);
|
STATIC XTAPI BOOLEAN CancelTimer(IN PKTIMER Timer);
|
||||||
STATIC XTAPI VOID ClearTimer(IN PKTIMER Timer);
|
STATIC XTAPI VOID ClearTimer(IN PKTIMER Timer);
|
||||||
@@ -28,6 +31,9 @@ namespace KE
|
|||||||
IN LARGE_INTEGER DueTime,
|
IN LARGE_INTEGER DueTime,
|
||||||
IN LONG Period,
|
IN LONG Period,
|
||||||
IN PKDPC Dpc);
|
IN PKDPC Dpc);
|
||||||
|
STATIC XTAPI VOID VerifySystemTimerExpiration(IN PKPROCESSOR_CONTROL_BLOCK Prcb,
|
||||||
|
IN PKTRAP_FRAME TrapFrame,
|
||||||
|
IN LARGE_INTEGER Time);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
STATIC XTAPI VOID RemoveTimer(IN OUT PKTIMER Timer);
|
STATIC XTAPI VOID RemoveTimer(IN OUT PKTIMER Timer);
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ namespace MM
|
|||||||
private:
|
private:
|
||||||
STATIC LOADER_MEMORY_DESCRIPTOR HardwareAllocationDescriptors[MM_HARDWARE_ALLOCATION_DESCRIPTORS];
|
STATIC LOADER_MEMORY_DESCRIPTOR HardwareAllocationDescriptors[MM_HARDWARE_ALLOCATION_DESCRIPTORS];
|
||||||
STATIC PVOID HardwareHeapStart;
|
STATIC PVOID HardwareHeapStart;
|
||||||
|
STATIC PHYSICAL_ADDRESS LowMemoryPhysicalAddress;
|
||||||
|
STATIC PVOID LowMemoryVirtualAddress;
|
||||||
STATIC ULONG UsedHardwareAllocationDescriptors;
|
STATIC ULONG UsedHardwareAllocationDescriptors;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -27,12 +29,19 @@ namespace MM
|
|||||||
IN BOOLEAN Aligned,
|
IN BOOLEAN Aligned,
|
||||||
IN ULONGLONG MaximumAddress,
|
IN ULONGLONG MaximumAddress,
|
||||||
OUT PPHYSICAL_ADDRESS Buffer);
|
OUT PPHYSICAL_ADDRESS Buffer);
|
||||||
STATIC XTAPI XTSTATUS AllocateRealModeMemory(IN PFN_NUMBER PageCount,
|
STATIC XTAPI XTSTATUS AllocateLowMemory(OUT PPHYSICAL_ADDRESS PhysicalAddress,
|
||||||
OUT PVOID *MemoryAddress);
|
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,
|
STATIC XTAPI XTSTATUS MapHardwareMemory(IN PHYSICAL_ADDRESS PhysicalAddress,
|
||||||
IN PFN_NUMBER PageCount,
|
IN PFN_NUMBER PageCount,
|
||||||
IN BOOLEAN FlushTlb,
|
IN BOOLEAN FlushTlb,
|
||||||
OUT PVOID *VirtualAddress);
|
OUT PVOID *VirtualAddress);
|
||||||
|
STATIC XTAPI XTSTATUS MapRealModeMemory(IN PHYSICAL_ADDRESS PhysicalAddress,
|
||||||
|
IN ULONG Size);
|
||||||
STATIC XTAPI VOID MarkHardwareMemoryWriteThrough(IN PVOID VirtualAddress,
|
STATIC XTAPI VOID MarkHardwareMemoryWriteThrough(IN PVOID VirtualAddress,
|
||||||
IN PFN_NUMBER PageCount);
|
IN PFN_NUMBER PageCount);
|
||||||
STATIC XTAPI VOID RemapHardwareMemory(IN PVOID VirtualAddress,
|
STATIC XTAPI VOID RemapHardwareMemory(IN PVOID VirtualAddress,
|
||||||
@@ -41,6 +50,8 @@ namespace MM
|
|||||||
STATIC XTAPI XTSTATUS UnmapHardwareMemory(IN PVOID VirtualAddress,
|
STATIC XTAPI XTSTATUS UnmapHardwareMemory(IN PVOID VirtualAddress,
|
||||||
IN PFN_NUMBER PageCount,
|
IN PFN_NUMBER PageCount,
|
||||||
IN BOOLEAN FlushTlb);
|
IN BOOLEAN FlushTlb);
|
||||||
|
STATIC XTAPI VOID UnmapRealModeMemory(IN PHYSICAL_ADDRESS PhysicalAddress,
|
||||||
|
IN ULONG Size);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#include <xtos.hh>
|
#include <xtos.hh>
|
||||||
|
|
||||||
|
|
||||||
/* Runtime Library */
|
/* Power Management */
|
||||||
namespace PO
|
namespace PO
|
||||||
{
|
{
|
||||||
class Idle
|
class Idle
|
||||||
|
|||||||
18
xtoskrnl/includes/ps.hh
Normal file
18
xtoskrnl/includes/ps.hh
Normal 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 */
|
||||||
25
xtoskrnl/includes/ps/process.hh
Normal file
25
xtoskrnl/includes/ps/process.hh
Normal 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 */
|
||||||
26
xtoskrnl/includes/ps/thread.hh
Normal file
26
xtoskrnl/includes/ps/thread.hh
Normal 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 */
|
||||||
@@ -24,4 +24,5 @@
|
|||||||
#include <ke.hh>
|
#include <ke.hh>
|
||||||
#include <mm.hh>
|
#include <mm.hh>
|
||||||
#include <po.hh>
|
#include <po.hh>
|
||||||
|
#include <ps.hh>
|
||||||
#include <rtl.hh>
|
#include <rtl.hh>
|
||||||
|
|||||||
36
xtoskrnl/kd/amd64/debug.cc
Normal file
36
xtoskrnl/kd/amd64/debug.cc
Normal 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);
|
||||||
|
}
|
||||||
@@ -9,6 +9,9 @@
|
|||||||
#include <xtos.hh>
|
#include <xtos.hh>
|
||||||
|
|
||||||
|
|
||||||
|
/* Debugger active flag */
|
||||||
|
BOOLEAN KD::Debugger::Active;
|
||||||
|
|
||||||
/* Debug I/O spinlock */
|
/* Debug I/O spinlock */
|
||||||
KSPIN_LOCK KD::DebugIo::DebugIoLock;
|
KSPIN_LOCK KD::DebugIo::DebugIoLock;
|
||||||
|
|
||||||
|
|||||||
@@ -57,12 +57,16 @@ VOID
|
|||||||
KD::DebugIo::DbgPrint(PCWSTR Format,
|
KD::DebugIo::DbgPrint(PCWSTR Format,
|
||||||
VA_LIST Arguments)
|
VA_LIST Arguments)
|
||||||
{
|
{
|
||||||
PLIST_ENTRY DispatchTableEntry;
|
|
||||||
PKD_DISPATCH_TABLE DispatchTable;
|
PKD_DISPATCH_TABLE DispatchTable;
|
||||||
|
PLIST_ENTRY DispatchTableEntry;
|
||||||
|
BOOLEAN BypassLocks;
|
||||||
|
|
||||||
/* Raise runlevel and acquire the Debug I/O lock */
|
/* Evaluate if the system is currently in a critical or debugging state */
|
||||||
KE::RaiseRunLevel RunLevel(HIGH_LEVEL);
|
BypassLocks = (KE::Crash::SystemCrashed() || KD::Debugger::DebuggerActive());
|
||||||
KE::SpinLockGuard SpinLock(&DebugIoLock);
|
|
||||||
|
/* 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 */
|
/* Iterate over all registered debug providers */
|
||||||
DispatchTableEntry = Providers.Flink;
|
DispatchTableEntry = Providers.Flink;
|
||||||
|
|||||||
74
xtoskrnl/kd/debug.cc
Normal file
74
xtoskrnl/kd/debug.cc
Normal 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
36
xtoskrnl/kd/i686/debug.cc
Normal 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
562
xtoskrnl/ke/affinity.cc
Normal 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,13 +22,12 @@
|
|||||||
*
|
*
|
||||||
* @since XT 1.0
|
* @since XT 1.0
|
||||||
*/
|
*/
|
||||||
|
XTASSEMBLY
|
||||||
XTFASTCALL
|
XTFASTCALL
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
KE::Dispatcher::SwitchContext(IN PKTHREAD CurrentThread,
|
KE::Dispatcher::SwitchContext(IN PKTHREAD CurrentThread,
|
||||||
IN KRUNLEVEL RunLevel)
|
IN KRUNLEVEL RunLevel)
|
||||||
{
|
{
|
||||||
BOOLEAN PendingApc;
|
|
||||||
|
|
||||||
/* Save non-volatile and XMM registers to the exception frame, align the stack and invoke the switch routine */
|
/* Save non-volatile and XMM registers to the exception frame, align the stack and invoke the switch routine */
|
||||||
__asm__ volatile("subq %[ExFrameSize], %%rsp\n"
|
__asm__ volatile("subq %[ExFrameSize], %%rsp\n"
|
||||||
"movq %%rbp, %c[ExRbp](%%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[ExXmm14](%%rsp), %%xmm14\n"
|
||||||
"movdqa %c[ExXmm15](%%rsp), %%xmm15\n"
|
"movdqa %c[ExXmm15](%%rsp), %%xmm15\n"
|
||||||
"addq %[ExFrameSize], %%rsp\n"
|
"addq %[ExFrameSize], %%rsp\n"
|
||||||
: "=a" (PendingApc)
|
"ret\n"
|
||||||
: "c" (CurrentThread),
|
:
|
||||||
"d" (RunLevel),
|
: [ExFrameSize] "i" (sizeof(KEXCEPTION_FRAME) - 8),
|
||||||
[ExFrameSize] "i" (sizeof(KEXCEPTION_FRAME) - 8),
|
|
||||||
[ExR12] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, R12)),
|
[ExR12] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, R12)),
|
||||||
[ExR13] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, R13)),
|
[ExR13] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, R13)),
|
||||||
[ExR14] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, R14)),
|
[ExR14] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, R14)),
|
||||||
@@ -93,9 +91,6 @@ KE::Dispatcher::SwitchContext(IN PKTHREAD CurrentThread,
|
|||||||
[ExXmm15] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Xmm15)),
|
[ExXmm15] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Xmm15)),
|
||||||
[SwitchRoutine] "i" (SwitchThreadStack)
|
[SwitchRoutine] "i" (SwitchThreadStack)
|
||||||
: "cc", "memory", "r8", "r9", "r10", "r11");
|
: "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
|
* @since XT 1.0
|
||||||
*/
|
*/
|
||||||
|
XTASSEMBLY
|
||||||
XTFASTCALL
|
XTFASTCALL
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
KE::Dispatcher::SwitchThreadStack(IN PKTHREAD CurrentThread,
|
KE::Dispatcher::SwitchThreadStack(IN PKTHREAD CurrentThread,
|
||||||
IN KRUNLEVEL RunLevel)
|
IN KRUNLEVEL RunLevel)
|
||||||
{
|
{
|
||||||
BOOLEAN PendingApc;
|
|
||||||
|
|
||||||
/* Preserve MXCSR, synchronize with CPUs, switch stack and call the switch routine */
|
/* Preserve MXCSR, synchronize with CPUs, switch stack and call the switch routine */
|
||||||
__asm__ volatile("pushq %%rbp\n"
|
__asm__ volatile("pushq %%rbp\n"
|
||||||
"subq %[FrameSize], %%rsp\n"
|
"subq %[FrameSize], %%rsp\n"
|
||||||
@@ -160,10 +154,9 @@ KE::Dispatcher::SwitchThreadStack(IN PKTHREAD CurrentThread,
|
|||||||
"ldmxcsr %c[SwMxCsr](%%rsp)\n"
|
"ldmxcsr %c[SwMxCsr](%%rsp)\n"
|
||||||
"addq %[FrameSize], %%rsp\n"
|
"addq %[FrameSize], %%rsp\n"
|
||||||
"popq %%rbp\n"
|
"popq %%rbp\n"
|
||||||
: "=a" (PendingApc)
|
"ret\n"
|
||||||
: "c" (CurrentThread),
|
:
|
||||||
"d" (RunLevel),
|
: [FrameSize] "i" (FIELD_OFFSET(KSWITCH_FRAME, Rbp)),
|
||||||
[FrameSize] "i" (FIELD_OFFSET(KSWITCH_FRAME, Rbp)),
|
|
||||||
[PrcbcCurrentThread] "i" (FIELD_OFFSET(KPROCESSOR_BLOCK, Prcb.CurrentThread)),
|
[PrcbcCurrentThread] "i" (FIELD_OFFSET(KPROCESSOR_BLOCK, Prcb.CurrentThread)),
|
||||||
[SwApcBypass] "i" (FIELD_OFFSET(KSWITCH_FRAME, ApcBypass)),
|
[SwApcBypass] "i" (FIELD_OFFSET(KSWITCH_FRAME, ApcBypass)),
|
||||||
[SwMxCsr] "i" (FIELD_OFFSET(KSWITCH_FRAME, MxCsr)),
|
[SwMxCsr] "i" (FIELD_OFFSET(KSWITCH_FRAME, MxCsr)),
|
||||||
@@ -171,7 +164,4 @@ KE::Dispatcher::SwitchThreadStack(IN PKTHREAD CurrentThread,
|
|||||||
[ThrdStack] "i" (FIELD_OFFSET(KTHREAD, KernelStack)),
|
[ThrdStack] "i" (FIELD_OFFSET(KTHREAD, KernelStack)),
|
||||||
[ThrdSwapBusy] "i" (FIELD_OFFSET(KTHREAD, SwapBusy))
|
[ThrdSwapBusy] "i" (FIELD_OFFSET(KTHREAD, SwapBusy))
|
||||||
: "cc", "memory", "r8", "r9", "r10", "r11");
|
: "cc", "memory", "r8", "r9", "r10", "r11");
|
||||||
|
|
||||||
/* Return the APC status */
|
|
||||||
return PendingApc;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,21 +46,30 @@ KE::KernelInit::BootstrapApplicationProcessor(IN PPROCESSOR_START_BLOCK StartBlo
|
|||||||
PO::Idle::InitializeProcessorIdleState(ControlBlock);
|
PO::Idle::InitializeProcessorIdleState(ControlBlock);
|
||||||
|
|
||||||
/* Save processor state */
|
/* Save processor state */
|
||||||
KE::Processor::SaveProcessorState(&ControlBlock->ProcessorState);
|
KE::Processor::SaveProcessorControlState(&ControlBlock->ProcessorState);
|
||||||
|
|
||||||
/* Initialize per-CPU spin lock queues */
|
/* Initialize per-CPU spin lock queues */
|
||||||
KE::SpinLock::InitializeLockQueues();
|
KE::SpinLock::InitializeLockQueues();
|
||||||
|
|
||||||
|
/* Initialize interrupt handlers */
|
||||||
|
InitializeInterruptHandlers();
|
||||||
|
|
||||||
/* Lower to APC runlevel */
|
/* Lower to APC runlevel */
|
||||||
KE::RunLevel::LowerRunLevel(APC_LEVEL);
|
KE::RunLevel::LowerRunLevel(APC_LEVEL);
|
||||||
|
|
||||||
/* Initialize local clock for this CPU */
|
/* Initialize local clock for this CPU */
|
||||||
HL::Timer::InitializeLocalClock();
|
HL::Timer::InitializeLocalClock();
|
||||||
|
|
||||||
/* Enter infinite loop */
|
/* Create and initialize IDLE thread */
|
||||||
DebugPrint(L"KernelInit::BootstrapApplicationProcessor() finished for CPU #%lu. Entering infinite loop.\n",
|
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);
|
ControlBlock->CpuNumber);
|
||||||
KE::Crash::HaltSystem();
|
KE::Dispatcher::EnterIdleLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -76,62 +85,65 @@ VOID
|
|||||||
KE::KernelInit::BootstrapKernel(VOID)
|
KE::KernelInit::BootstrapKernel(VOID)
|
||||||
{
|
{
|
||||||
PKPROCESSOR_CONTROL_BLOCK Prcb;
|
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();
|
Prcb = KE::Processor::GetCurrentProcessorControlBlock();
|
||||||
CurrentThread = KE::Processor::GetCurrentThread();
|
|
||||||
|
|
||||||
/* Get current process */
|
|
||||||
CurrentProcess = CurrentThread->ApcState.Process;
|
|
||||||
|
|
||||||
/* Initialize CPU power state structures */
|
/* Initialize CPU power state structures */
|
||||||
PO::Idle::InitializeProcessorIdleState(Prcb);
|
PO::Idle::InitializeProcessorIdleState(Prcb);
|
||||||
|
|
||||||
/* Save processor state */
|
/* Save processor state */
|
||||||
KE::Processor::SaveProcessorState(&Prcb->ProcessorState);
|
KE::Processor::SaveProcessorControlState(&Prcb->ProcessorState);
|
||||||
|
|
||||||
/* Initialize spin locks */
|
/* Initialize spin locks */
|
||||||
KE::SpinLock::InitializeAllLocks();
|
KE::SpinLock::InitializeAllLocks();
|
||||||
KE::SpinLock::InitializeLockQueues();
|
KE::SpinLock::InitializeLockQueues();
|
||||||
|
|
||||||
|
/* Initialize interrupt handlers */
|
||||||
|
InitializeInterruptHandlers();
|
||||||
|
|
||||||
/* Lower to APC runlevel */
|
/* Lower to APC runlevel */
|
||||||
KE::RunLevel::LowerRunLevel(APC_LEVEL);
|
KE::RunLevel::LowerRunLevel(APC_LEVEL);
|
||||||
|
|
||||||
/* Initialize XTOS kernel */
|
/* Initialize XTOS kernel */
|
||||||
InitializeKernel();
|
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 */
|
/* Initialize Memory Manager */
|
||||||
MM::Manager::InitializeMemoryManager();
|
MM::Manager::InitializeMemoryManager();
|
||||||
|
|
||||||
/* Enable shadow buffer for framebuffer */
|
/* Enable shadow buffer for framebuffer */
|
||||||
HL::FrameBuffer::EnableShadowBuffer();
|
HL::FrameBuffer::EnableShadowBuffer();
|
||||||
|
|
||||||
|
/* Create and initialize IDLE process */
|
||||||
|
PS::Process::CreateIdleProcess(Prcb);
|
||||||
|
|
||||||
/* Start all application processors */
|
/* Start all application processors */
|
||||||
KE::Processor::InitializeProcessorBlocks();
|
KE::Processor::InitializeProcessorBlocks();
|
||||||
|
HL::Cpu::InitializeProcessorAffinity();
|
||||||
HL::Cpu::StartAllProcessors();
|
HL::Cpu::StartAllProcessors();
|
||||||
|
|
||||||
/* Enter infinite loop */
|
/* Register DISPATCH interrupt handler */
|
||||||
DebugPrint(L"KernelInit::BootstrapKernel() finished. Entering infinite loop.\n");
|
HL::Irq::RegisterSystemInterruptHandler(APIC_VECTOR_DPC, KE::Dispatcher::HandleDispatchInterrupt);
|
||||||
KE::Crash::HaltSystem();
|
|
||||||
|
/* 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"
|
__asm__ volatile("movq %[Stack], %%rsp\n"
|
||||||
"subq %[TotalSize], %%rsp\n"
|
"subq %[TotalSize], %%rsp\n"
|
||||||
"xorq %%rbp, %%rbp\n"
|
"xorq %%rbp, %%rbp\n"
|
||||||
"jmp *%[TargetRoutine]\n"
|
"call *%[TargetRoutine]\n"
|
||||||
:
|
:
|
||||||
: [Stack] "r" (Stack),
|
: [Stack] "r" (Stack),
|
||||||
[TargetRoutine] "r" (StartKernel),
|
[TargetRoutine] "r" (StartKernel),
|
||||||
|
|||||||
@@ -66,6 +66,21 @@ KE::Processor::GetCurrentThread(VOID)
|
|||||||
return (PKTHREAD)AR::CpuFunctions::ReadGSQuadWord(FIELD_OFFSET(KPROCESSOR_BLOCK, Prcb.CurrentThread));
|
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.
|
* Gets the processor block for the specified processor number.
|
||||||
*
|
*
|
||||||
@@ -122,6 +137,9 @@ KE::Processor::InitializeProcessorBlocks()
|
|||||||
/* Zero the array initially */
|
/* Zero the array initially */
|
||||||
RTL::Memory::ZeroMemory(ProcessorBlocks, InstalledCpus * sizeof(PKPROCESSOR_BLOCK));
|
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 success */
|
||||||
return STATUS_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
|
* @param TrapFrame
|
||||||
* Supplies a pointer to the processor state structure.
|
* 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.
|
* @return This routine does not return any value.
|
||||||
*
|
*
|
||||||
@@ -189,7 +217,223 @@ KE::Processor::RegisterProcessorBlock(ULONG CpuNumber,
|
|||||||
*/
|
*/
|
||||||
XTAPI
|
XTAPI
|
||||||
VOID
|
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 */
|
/* Save CR registers */
|
||||||
CpuState->SpecialRegisters.Cr0 = AR::CpuFunctions::ReadControlRegister(0);
|
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::StoreLocalDescriptorTable(&CpuState->SpecialRegisters.Ldtr);
|
||||||
AR::CpuFunctions::StoreTaskRegister(&CpuState->SpecialRegisters.Tr);
|
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);
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,11 +4,234 @@
|
|||||||
* FILE: xtoskrnl/ke/panic.cc
|
* FILE: xtoskrnl/ke/panic.cc
|
||||||
* DESCRIPTION: System shutdown and kernel panic mechanism
|
* DESCRIPTION: System shutdown and kernel panic mechanism
|
||||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||||
|
* Aiken Harris <harraiken91@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <xtos.hh>
|
#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.
|
* Halts the system.
|
||||||
*
|
*
|
||||||
@@ -43,6 +266,7 @@ XTAPI
|
|||||||
VOID
|
VOID
|
||||||
KE::Crash::Panic(IN ULONG Code)
|
KE::Crash::Panic(IN ULONG Code)
|
||||||
{
|
{
|
||||||
|
/* Call panic function */
|
||||||
Panic(Code, 0, 0, 0, 0);
|
Panic(Code, 0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +300,115 @@ KE::Crash::Panic(IN ULONG Code,
|
|||||||
IN ULONG_PTR Parameter3,
|
IN ULONG_PTR Parameter3,
|
||||||
IN ULONG_PTR Parameter4)
|
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",
|
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);
|
Code, Parameter1, Parameter2, Parameter3, Parameter4);
|
||||||
|
|
||||||
|
/* Halt system */
|
||||||
HaltSystem();
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,6 +12,15 @@
|
|||||||
/* Kernel initialization block passed by boot loader */
|
/* Kernel initialization block passed by boot loader */
|
||||||
PKERNEL_INITIALIZATION_BLOCK KE::BootInformation::InitializationBlock = {};
|
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 */
|
/* Kernel initial process */
|
||||||
EPROCESS KE::KProcess::InitialProcess;
|
EPROCESS KE::KProcess::InitialProcess;
|
||||||
|
|
||||||
@@ -95,3 +104,6 @@ LONG KE::SystemTime::TickOffset;
|
|||||||
|
|
||||||
/* The runtime adjustment value applied to the system clock at each interrupt */
|
/* The runtime adjustment value applied to the system clock at each interrupt */
|
||||||
ULONG KE::SystemTime::TimeAdjustment;
|
ULONG KE::SystemTime::TimeAdjustment;
|
||||||
|
|
||||||
|
/* Kernel timer table containing a list of active timers */
|
||||||
|
LIST_ENTRY KE::Timer::TimerTableListHead[KTIMER_TABLE_SIZE];
|
||||||
|
|||||||
@@ -4,11 +4,82 @@
|
|||||||
* FILE: xtoskrnl/ke/dispatch.cc
|
* FILE: xtoskrnl/ke/dispatch.cc
|
||||||
* DESCRIPTION: Kernel Thread Dispatcher
|
* DESCRIPTION: Kernel Thread Dispatcher
|
||||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||||
|
* Aiken Harris <harraiken91@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <xtos.hh>
|
#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.
|
* 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);
|
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.
|
* Updates the runtime quantum of the currently executing thread and handles preemption.
|
||||||
*
|
*
|
||||||
@@ -47,4 +137,101 @@ VOID
|
|||||||
KE::Dispatcher::UpdateRunTime(IN PKTRAP_FRAME TrapFrame,
|
KE::Dispatcher::UpdateRunTime(IN PKTRAP_FRAME TrapFrame,
|
||||||
IN KRUNLEVEL RunLevel)
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,13 +22,12 @@
|
|||||||
*
|
*
|
||||||
* @since XT 1.0
|
* @since XT 1.0
|
||||||
*/
|
*/
|
||||||
|
XTASSEMBLY
|
||||||
XTFASTCALL
|
XTFASTCALL
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
KE::Dispatcher::SwitchContext(IN PKTHREAD CurrentThread,
|
KE::Dispatcher::SwitchContext(IN PKTHREAD CurrentThread,
|
||||||
IN KRUNLEVEL RunLevel)
|
IN KRUNLEVEL RunLevel)
|
||||||
{
|
{
|
||||||
BOOLEAN PendingApc;
|
|
||||||
|
|
||||||
/* Save registers to the exception frame and invoke the stack switch routine */
|
/* Save registers to the exception frame and invoke the stack switch routine */
|
||||||
__asm__ volatile("subl %[ExFrameSize], %%esp\n"
|
__asm__ volatile("subl %[ExFrameSize], %%esp\n"
|
||||||
"movl %%esi, %c[ExEsi](%%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[ExEdi](%%esp), %%edi\n"
|
||||||
"movl %c[ExEsi](%%esp), %%esi\n"
|
"movl %c[ExEsi](%%esp), %%esi\n"
|
||||||
"addl %[ExFrameSize], %%esp\n"
|
"addl %[ExFrameSize], %%esp\n"
|
||||||
: "=a" (PendingApc)
|
"ret\n"
|
||||||
: "c" (CurrentThread),
|
:
|
||||||
"d" (RunLevel),
|
: [ExFrameSize] "i" (sizeof(KEXCEPTION_FRAME) - 4),
|
||||||
[ExFrameSize] "i" (sizeof(KEXCEPTION_FRAME) - 4),
|
|
||||||
[ExEbp] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Ebp)),
|
[ExEbp] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Ebp)),
|
||||||
[ExEbx] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Ebx)),
|
[ExEbx] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Ebx)),
|
||||||
[ExEdi] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Edi)),
|
[ExEdi] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Edi)),
|
||||||
[ExEsi] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Esi)),
|
[ExEsi] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Esi)),
|
||||||
[SwitchRoutine] "i" (SwitchThreadStack)
|
[SwitchRoutine] "i" (SwitchThreadStack)
|
||||||
: "cc", "memory");
|
: "cc", "memory");
|
||||||
|
|
||||||
/* Return the APC status */
|
|
||||||
return PendingApc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -92,13 +87,12 @@ KE::Dispatcher::SwitchThreadContext(IN PKTHREAD CurrentThread,
|
|||||||
*
|
*
|
||||||
* @since XT 1.0
|
* @since XT 1.0
|
||||||
*/
|
*/
|
||||||
|
XTASSEMBLY
|
||||||
XTFASTCALL
|
XTFASTCALL
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
KE::Dispatcher::SwitchThreadStack(IN PKTHREAD CurrentThread,
|
KE::Dispatcher::SwitchThreadStack(IN PKTHREAD CurrentThread,
|
||||||
IN KRUNLEVEL RunLevel)
|
IN KRUNLEVEL RunLevel)
|
||||||
{
|
{
|
||||||
BOOLEAN PendingApc;
|
|
||||||
|
|
||||||
/* Save old state, synchronize with CPUs, switch stack and call the switch routine */
|
/* Save old state, synchronize with CPUs, switch stack and call the switch routine */
|
||||||
__asm__ volatile("subl %[FrameSize], %%esp\n"
|
__asm__ volatile("subl %[FrameSize], %%esp\n"
|
||||||
"movl %%fs:%c[PrcbcCurrentThread], %%ebx\n"
|
"movl %%fs:%c[PrcbcCurrentThread], %%ebx\n"
|
||||||
@@ -116,10 +110,9 @@ KE::Dispatcher::SwitchThreadStack(IN PKTHREAD CurrentThread,
|
|||||||
"movzbl %c[SwApcBypass](%%esp), %%edx\n"
|
"movzbl %c[SwApcBypass](%%esp), %%edx\n"
|
||||||
"call %P[SwitchRoutine]\n"
|
"call %P[SwitchRoutine]\n"
|
||||||
"addl %[FrameSize], %%esp\n"
|
"addl %[FrameSize], %%esp\n"
|
||||||
: "=a" (PendingApc)
|
"ret\n"
|
||||||
: "c" (CurrentThread),
|
:
|
||||||
"d" (RunLevel),
|
: [FrameSize] "i" (sizeof(KSWITCH_FRAME) - 4),
|
||||||
[FrameSize] "i" (sizeof(KSWITCH_FRAME) - 4),
|
|
||||||
[PrcbcCurrentThread] "i" (FIELD_OFFSET(KPROCESSOR_BLOCK, Prcb.CurrentThread)),
|
[PrcbcCurrentThread] "i" (FIELD_OFFSET(KPROCESSOR_BLOCK, Prcb.CurrentThread)),
|
||||||
[SwApcBypass] "i" (FIELD_OFFSET(KSWITCH_FRAME, ApcBypassDisabled)),
|
[SwApcBypass] "i" (FIELD_OFFSET(KSWITCH_FRAME, ApcBypassDisabled)),
|
||||||
[SwExceptionList] "i" (FIELD_OFFSET(KSWITCH_FRAME, ExceptionList)),
|
[SwExceptionList] "i" (FIELD_OFFSET(KSWITCH_FRAME, ExceptionList)),
|
||||||
@@ -128,7 +121,4 @@ KE::Dispatcher::SwitchThreadStack(IN PKTHREAD CurrentThread,
|
|||||||
[ThrdStack] "i" (FIELD_OFFSET(KTHREAD, KernelStack)),
|
[ThrdStack] "i" (FIELD_OFFSET(KTHREAD, KernelStack)),
|
||||||
[ThrdSwapBusy] "i" (FIELD_OFFSET(KTHREAD, SwapBusy))
|
[ThrdSwapBusy] "i" (FIELD_OFFSET(KTHREAD, SwapBusy))
|
||||||
: "cc", "memory");
|
: "cc", "memory");
|
||||||
|
|
||||||
/* Return the APC status */
|
|
||||||
return PendingApc;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,21 +46,30 @@ KE::KernelInit::BootstrapApplicationProcessor(IN PPROCESSOR_START_BLOCK StartBlo
|
|||||||
PO::Idle::InitializeProcessorIdleState(ControlBlock);
|
PO::Idle::InitializeProcessorIdleState(ControlBlock);
|
||||||
|
|
||||||
/* Save processor state */
|
/* Save processor state */
|
||||||
KE::Processor::SaveProcessorState(&ControlBlock->ProcessorState);
|
KE::Processor::SaveProcessorControlState(&ControlBlock->ProcessorState);
|
||||||
|
|
||||||
/* Initialize per-CPU spin lock queues */
|
/* Initialize per-CPU spin lock queues */
|
||||||
KE::SpinLock::InitializeLockQueues();
|
KE::SpinLock::InitializeLockQueues();
|
||||||
|
|
||||||
|
/* Initialize interrupt handlers */
|
||||||
|
InitializeInterruptHandlers();
|
||||||
|
|
||||||
/* Lower to APC runlevel */
|
/* Lower to APC runlevel */
|
||||||
KE::RunLevel::LowerRunLevel(APC_LEVEL);
|
KE::RunLevel::LowerRunLevel(APC_LEVEL);
|
||||||
|
|
||||||
/* Initialize local clock for this CPU */
|
/* Initialize local clock for this CPU */
|
||||||
HL::Timer::InitializeLocalClock();
|
HL::Timer::InitializeLocalClock();
|
||||||
|
|
||||||
/* Enter infinite loop */
|
/* Create and initialize IDLE thread */
|
||||||
DebugPrint(L"KernelInit::BootstrapApplicationProcessor() finished for CPU #%lu. Entering infinite loop.\n",
|
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);
|
ControlBlock->CpuNumber);
|
||||||
KE::Crash::HaltSystem();
|
KE::Dispatcher::EnterIdleLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -76,62 +85,65 @@ VOID
|
|||||||
KE::KernelInit::BootstrapKernel(VOID)
|
KE::KernelInit::BootstrapKernel(VOID)
|
||||||
{
|
{
|
||||||
PKPROCESSOR_CONTROL_BLOCK Prcb;
|
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();
|
Prcb = KE::Processor::GetCurrentProcessorControlBlock();
|
||||||
CurrentThread = KE::Processor::GetCurrentThread();
|
|
||||||
|
|
||||||
/* Get current process */
|
|
||||||
CurrentProcess = CurrentThread->ApcState.Process;
|
|
||||||
|
|
||||||
/* Initialize CPU power state structures */
|
/* Initialize CPU power state structures */
|
||||||
PO::Idle::InitializeProcessorIdleState(Prcb);
|
PO::Idle::InitializeProcessorIdleState(Prcb);
|
||||||
|
|
||||||
/* Save processor state */
|
/* Save processor state */
|
||||||
KE::Processor::SaveProcessorState(&Prcb->ProcessorState);
|
KE::Processor::SaveProcessorControlState(&Prcb->ProcessorState);
|
||||||
|
|
||||||
/* Initialize spin locks */
|
/* Initialize spin locks */
|
||||||
KE::SpinLock::InitializeAllLocks();
|
KE::SpinLock::InitializeAllLocks();
|
||||||
KE::SpinLock::InitializeLockQueues();
|
KE::SpinLock::InitializeLockQueues();
|
||||||
|
|
||||||
|
/* Initialize interrupt handlers */
|
||||||
|
InitializeInterruptHandlers();
|
||||||
|
|
||||||
/* Lower to APC runlevel */
|
/* Lower to APC runlevel */
|
||||||
KE::RunLevel::LowerRunLevel(APC_LEVEL);
|
KE::RunLevel::LowerRunLevel(APC_LEVEL);
|
||||||
|
|
||||||
/* Initialize XTOS kernel */
|
/* Initialize XTOS kernel */
|
||||||
InitializeKernel();
|
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 */
|
/* Initialize Memory Manager */
|
||||||
MM::Manager::InitializeMemoryManager();
|
MM::Manager::InitializeMemoryManager();
|
||||||
|
|
||||||
/* Enable shadow buffer for framebuffer */
|
/* Enable shadow buffer for framebuffer */
|
||||||
HL::FrameBuffer::EnableShadowBuffer();
|
HL::FrameBuffer::EnableShadowBuffer();
|
||||||
|
|
||||||
|
/* Create and initialize IDLE process */
|
||||||
|
PS::Process::CreateIdleProcess(Prcb);
|
||||||
|
|
||||||
/* Start all application processors */
|
/* Start all application processors */
|
||||||
KE::Processor::InitializeProcessorBlocks();
|
KE::Processor::InitializeProcessorBlocks();
|
||||||
|
HL::Cpu::InitializeProcessorAffinity();
|
||||||
HL::Cpu::StartAllProcessors();
|
HL::Cpu::StartAllProcessors();
|
||||||
|
|
||||||
/* Enter infinite loop */
|
/* Register DISPATCH interrupt handler */
|
||||||
DebugPrint(L"KernelInit::BootstrapKernel() finished. Entering infinite loop.\n");
|
HL::Irq::RegisterSystemInterruptHandler(APIC_VECTOR_DPC, KE::Dispatcher::HandleDispatchInterrupt);
|
||||||
KE::Crash::HaltSystem();
|
|
||||||
|
/* 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ KE::KThread::InitializeThreadContext(IN PKTHREAD Thread,
|
|||||||
|
|
||||||
/* Disable coprocessor floating point state */
|
/* Disable coprocessor floating point state */
|
||||||
Thread->NpxState = NPX_STATE_UNLOADED;
|
Thread->NpxState = NPX_STATE_UNLOADED;
|
||||||
Thread->Header.NpxIrql = PASSIVE_LEVEL;
|
Thread->NpxRunLevel = PASSIVE_LEVEL;
|
||||||
|
|
||||||
/* Set initial floating point state */
|
/* Set initial floating point state */
|
||||||
FxSaveFormat = (PFX_SAVE_FORMAT)ContextRecord->ExtendedRegisters;
|
FxSaveFormat = (PFX_SAVE_FORMAT)ContextRecord->ExtendedRegisters;
|
||||||
|
|||||||
@@ -66,6 +66,21 @@ KE::Processor::GetCurrentThread(VOID)
|
|||||||
return (PKTHREAD)AR::CpuFunctions::ReadFSDualWord(FIELD_OFFSET(KPROCESSOR_BLOCK, Prcb.CurrentThread));
|
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.
|
* Gets the processor block for the specified processor number.
|
||||||
*
|
*
|
||||||
@@ -122,6 +137,9 @@ KE::Processor::InitializeProcessorBlocks()
|
|||||||
/* Zero the array initially */
|
/* Zero the array initially */
|
||||||
RTL::Memory::ZeroMemory(ProcessorBlocks, InstalledCpus * sizeof(PKPROCESSOR_BLOCK));
|
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 success */
|
||||||
return STATUS_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
|
* @param TrapFrame
|
||||||
* Supplies a pointer to the processor state structure.
|
* 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.
|
* @return This routine does not return any value.
|
||||||
*
|
*
|
||||||
@@ -189,7 +217,183 @@ KE::Processor::RegisterProcessorBlock(ULONG CpuNumber,
|
|||||||
*/
|
*/
|
||||||
XTAPI
|
XTAPI
|
||||||
VOID
|
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 */
|
/* Save CR registers */
|
||||||
CpuState->SpecialRegisters.Cr0 = AR::CpuFunctions::ReadControlRegister(0);
|
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::StoreLocalDescriptorTable(&CpuState->SpecialRegisters.Ldtr);
|
||||||
AR::CpuFunctions::StoreTaskRegister(&CpuState->SpecialRegisters.Tr);
|
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
247
xtoskrnl/ke/ipi.cc
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,21 @@
|
|||||||
#include <xtos.hh>
|
#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.
|
* Retrieves a pointer to the system's initial executive process object.
|
||||||
*
|
*
|
||||||
@@ -23,6 +38,58 @@ KE::KProcess::GetInitialProcess(VOID)
|
|||||||
return &InitialProcess;
|
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.
|
* Initializes the process.
|
||||||
*
|
*
|
||||||
@@ -32,8 +99,8 @@ KE::KProcess::GetInitialProcess(VOID)
|
|||||||
* @param Priority
|
* @param Priority
|
||||||
* Specifies the process priority.
|
* Specifies the process priority.
|
||||||
*
|
*
|
||||||
* @param Affinity
|
* @param AffinityMap
|
||||||
* Specifies a process affinity designating processors on which process can run.
|
* Specifies a process affinity map designating processors on which process can run.
|
||||||
*
|
*
|
||||||
* @param DirectoryTable
|
* @param DirectoryTable
|
||||||
* Supplies a pointer to the directory table.
|
* Supplies a pointer to the directory table.
|
||||||
@@ -49,11 +116,13 @@ XTAPI
|
|||||||
VOID
|
VOID
|
||||||
KE::KProcess::InitializeProcess(IN OUT PKPROCESS Process,
|
KE::KProcess::InitializeProcess(IN OUT PKPROCESS Process,
|
||||||
IN KPRIORITY Priority,
|
IN KPRIORITY Priority,
|
||||||
IN KAFFINITY Affinity,
|
IN PKAFFINITY_MAP AffinityMap,
|
||||||
IN PULONG_PTR DirectoryTable,
|
IN PULONG_PTR DirectoryTable,
|
||||||
IN BOOLEAN Alignment)
|
IN BOOLEAN Alignment)
|
||||||
{
|
{
|
||||||
/* Initialize process dispatcher header */
|
/* Initialize process dispatcher header */
|
||||||
|
Process->Header.SignalState = 0;
|
||||||
|
Process->Header.Size = sizeof(KPROCESS) / sizeof(LONG);
|
||||||
Process->Header.Type = ProcessObject;
|
Process->Header.Type = ProcessObject;
|
||||||
|
|
||||||
/* Initialize process wait list */
|
/* Initialize process wait list */
|
||||||
@@ -64,15 +133,23 @@ KE::KProcess::InitializeProcess(IN OUT PKPROCESS Process,
|
|||||||
RtlInitializeListHead(&Process->ReadyListHead);
|
RtlInitializeListHead(&Process->ReadyListHead);
|
||||||
RtlInitializeListHead(&Process->ThreadListHead);
|
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 */
|
/* Set base process properties */
|
||||||
Process->BasePriority = Priority;
|
Process->BasePriority = Priority;
|
||||||
Process->Affinity = Affinity;
|
|
||||||
Process->AutoAlignment = Alignment;
|
Process->AutoAlignment = Alignment;
|
||||||
|
|
||||||
|
/* Set directory tables */
|
||||||
Process->DirectoryTable[0] = DirectoryTable[0];
|
Process->DirectoryTable[0] = DirectoryTable[0];
|
||||||
Process->DirectoryTable[1] = DirectoryTable[1];
|
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;
|
Process->Quantum = THREAD_QUANTUM;
|
||||||
|
|
||||||
/* Set IOPM offset */
|
/* Set IOPM offset */
|
||||||
|
|||||||
@@ -9,9 +9,6 @@
|
|||||||
#include <xtos.hh>
|
#include <xtos.hh>
|
||||||
|
|
||||||
|
|
||||||
/* Use routines from Kernel Library */
|
|
||||||
using namespace KE;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This routine starts up the XT kernel. It is called by boot loader.
|
* This routine starts up the XT kernel. It is called by boot loader.
|
||||||
*
|
*
|
||||||
@@ -22,6 +19,7 @@ using namespace KE;
|
|||||||
*
|
*
|
||||||
* @since XT 1.0
|
* @since XT 1.0
|
||||||
*/
|
*/
|
||||||
|
XTCLINK
|
||||||
XTAPI
|
XTAPI
|
||||||
VOID
|
VOID
|
||||||
KeStartXtSystem(IN PKERNEL_INITIALIZATION_BLOCK Parameters)
|
KeStartXtSystem(IN PKERNEL_INITIALIZATION_BLOCK Parameters)
|
||||||
|
|||||||
@@ -23,6 +23,76 @@ KE::KThread::GetInitialThread(VOID)
|
|||||||
return &InitialThread;
|
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.
|
* Initializes the thread.
|
||||||
*
|
*
|
||||||
@@ -75,8 +145,10 @@ KE::KThread::InitializeThread(IN PKPROCESS Process,
|
|||||||
Allocation = FALSE;
|
Allocation = FALSE;
|
||||||
|
|
||||||
/* Initialize thread dispatcher header */
|
/* Initialize thread dispatcher header */
|
||||||
Thread->Header.Type = ThreadObject;
|
|
||||||
Thread->Header.SignalState = 0;
|
Thread->Header.SignalState = 0;
|
||||||
|
Thread->Header.Size = sizeof(KTHREAD) / sizeof(LONG);
|
||||||
|
Thread->Header.DebugActive = FALSE;
|
||||||
|
Thread->Header.Type = ThreadObject;
|
||||||
|
|
||||||
/* Initialize thread wait list */
|
/* Initialize thread wait list */
|
||||||
RTL::LinkedList::InitializeListHead(&Thread->Header.WaitListHead);
|
RTL::LinkedList::InitializeListHead(&Thread->Header.WaitListHead);
|
||||||
@@ -99,15 +171,18 @@ KE::KThread::InitializeThread(IN PKPROCESS Process,
|
|||||||
/* Set priority adjustment reason */
|
/* Set priority adjustment reason */
|
||||||
Thread->AdjustReason = AdjustNone;
|
Thread->AdjustReason = AdjustNone;
|
||||||
|
|
||||||
|
/* Set the thread service table */
|
||||||
|
Thread->ServiceTable = KE::SystemServices::GetSystemServicesDescriptorTable();
|
||||||
|
|
||||||
/* Initialize thread lock */
|
/* Initialize thread lock */
|
||||||
KE::SpinLock::InitializeSpinLock(&Thread->ThreadLock);
|
KE::SpinLock::InitializeSpinLock(&Thread->ThreadLock);
|
||||||
|
|
||||||
/* Initialize thread APC */
|
/* Initialize thread APC */
|
||||||
Thread->ApcStatePointer[0] = &Thread->ApcState;
|
|
||||||
Thread->ApcStatePointer[1] = &Thread->SavedApcState;
|
|
||||||
Thread->ApcQueueable = TRUE;
|
Thread->ApcQueueable = TRUE;
|
||||||
Thread->ApcState.Process = Process;
|
Thread->ApcState.Process = Process;
|
||||||
Thread->Process = Process;
|
Thread->ApcStateIndex = OriginalApcEnvironment;
|
||||||
|
Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->ApcState;
|
||||||
|
Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->SavedApcState;
|
||||||
|
|
||||||
/* Initialize APC list heads */
|
/* Initialize APC list heads */
|
||||||
RTL::LinkedList::InitializeListHead(&Thread->ApcState.ApcListHead[KernelMode]);
|
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.Flink = &(&Thread->Timer)->Header.WaitListHead;
|
||||||
TimerWaitBlock->WaitListEntry.Blink = &(&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->EnvironmentBlock = (PTHREAD_ENVIRONMENT_BLOCK)EnvironmentBlock;
|
||||||
|
Thread->Process = Process;
|
||||||
|
|
||||||
/* Make sure there is a valid stack available */
|
/* Make sure there is a valid stack available */
|
||||||
if(!Stack)
|
if(!Stack)
|
||||||
@@ -150,6 +226,7 @@ KE::KThread::InitializeThread(IN PKPROCESS Process,
|
|||||||
Allocation = TRUE;
|
Allocation = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Setup thread stack */
|
||||||
Thread->InitialStack = Stack;
|
Thread->InitialStack = Stack;
|
||||||
Thread->StackBase = Stack;
|
Thread->StackBase = Stack;
|
||||||
Thread->StackLimit = (PVOID)((ULONG_PTR)Stack - KERNEL_STACK_SIZE);
|
Thread->StackLimit = (PVOID)((ULONG_PTR)Stack - KERNEL_STACK_SIZE);
|
||||||
@@ -200,7 +277,7 @@ KE::KThread::InitializeThread(IN PKPROCESS Process,
|
|||||||
*/
|
*/
|
||||||
XTAPI
|
XTAPI
|
||||||
VOID
|
VOID
|
||||||
KE::KThread::StartThread(IN PKTHREAD Thread)
|
KE::KThread::StartThread(IN OUT PKTHREAD Thread)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
UNIMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|||||||
25
xtoskrnl/ke/sysserv.cc
Normal file
25
xtoskrnl/ke/sysserv.cc
Normal 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;
|
||||||
|
}
|
||||||
@@ -152,6 +152,7 @@ KE::SystemTime::UpdateSystemTime(IN PKTRAP_FRAME TrapFrame,
|
|||||||
IN KRUNLEVEL RunLevel)
|
IN KRUNLEVEL RunLevel)
|
||||||
{
|
{
|
||||||
LARGE_INTEGER InterruptTime, SystemTime;
|
LARGE_INTEGER InterruptTime, SystemTime;
|
||||||
|
PKPROCESSOR_CONTROL_BLOCK ControlBlock;
|
||||||
LONG CurrentTickOffset;
|
LONG CurrentTickOffset;
|
||||||
|
|
||||||
/* Advance the global interrupt time on every hardware tick */
|
/* 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 */
|
/* Atomically consume the current tick budget and retrieve the pre-decrement value */
|
||||||
CurrentTickOffset = RTL::Atomic::ExchangeAdd32((PLONG)&TickOffset, -(LONG)Increment);
|
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 */
|
/* Determine whether the accumulated increments have crossed the full tick boundary */
|
||||||
if(CurrentTickOffset <= (LONG)Increment)
|
if(CurrentTickOffset <= (LONG)Increment)
|
||||||
{
|
{
|
||||||
@@ -170,8 +177,9 @@ KE::SystemTime::UpdateSystemTime(IN PKTRAP_FRAME TrapFrame,
|
|||||||
SystemTime.QuadPart += TimeAdjustment;
|
SystemTime.QuadPart += TimeAdjustment;
|
||||||
KE::SharedData::SetSystemTime(SystemTime);
|
KE::SharedData::SetSystemTime(SystemTime);
|
||||||
|
|
||||||
/* Update the tick count */
|
/* Update the tick count and reverify the system timer expiration */
|
||||||
KE::SharedData::IncrementTickCount();
|
KE::SharedData::IncrementTickCount();
|
||||||
|
KE::Timer::VerifySystemTimerExpiration(ControlBlock, TrapFrame, InterruptTime);
|
||||||
|
|
||||||
/* Reload the tick offset accumulator for the next full tick period */
|
/* Reload the tick offset accumulator for the next full tick period */
|
||||||
TickOffset += MaximumIncrement;
|
TickOffset += MaximumIncrement;
|
||||||
@@ -179,4 +187,9 @@ KE::SystemTime::UpdateSystemTime(IN PKTRAP_FRAME TrapFrame,
|
|||||||
/* Update processor and thread runtime accounting */
|
/* Update processor and thread runtime accounting */
|
||||||
KE::Dispatcher::UpdateRunTime(TrapFrame, RunLevel);
|
KE::Dispatcher::UpdateRunTime(TrapFrame, RunLevel);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Increment the interrupt count */
|
||||||
|
ControlBlock->InterruptCount++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
* FILE: xtoskrnl/ke/timer.cc
|
* FILE: xtoskrnl/ke/timer.cc
|
||||||
* DESCRIPTION: Kernel timer object support
|
* DESCRIPTION: Kernel timer object support
|
||||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||||
|
* Aiken Harris <harraiken91@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <xtos.hh>
|
#include <xtos.hh>
|
||||||
@@ -156,6 +157,25 @@ KE::Timer::QueryTimer(IN PKTIMER Timer)
|
|||||||
return DueTime;
|
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.
|
* 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
|
* @param Prcb
|
||||||
* Supplies a pointer to a timer object.
|
* 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.
|
* @return This routine does not return any value.
|
||||||
*
|
*
|
||||||
@@ -197,9 +224,37 @@ KE::Timer::SetTimer(IN PKTIMER Timer,
|
|||||||
*/
|
*/
|
||||||
XTAPI
|
XTAPI
|
||||||
VOID
|
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 */
|
LARGE_INTEGER TickCount;
|
||||||
Timer->Header.Inserted = FALSE;
|
ULONG TimerHand;
|
||||||
RTL::LinkedList::RemoveEntryList(&Timer->TimerListEntry);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -176,6 +176,7 @@ MM::Pte::MapP5E(IN PVOID StartAddress,
|
|||||||
IN PMMP5E TemplateP5e)
|
IN PMMP5E TemplateP5e)
|
||||||
{
|
{
|
||||||
PMMP5E EndSpace, PointerP5e;
|
PMMP5E EndSpace, PointerP5e;
|
||||||
|
PFN_NUMBER PageFrameNumber;
|
||||||
|
|
||||||
/* Get P5E addresses */
|
/* Get P5E addresses */
|
||||||
PointerP5e = MM::Paging::GetP5eAddress(StartAddress);
|
PointerP5e = MM::Paging::GetP5eAddress(StartAddress);
|
||||||
@@ -187,8 +188,18 @@ MM::Pte::MapP5E(IN PVOID StartAddress,
|
|||||||
/* Check if P5E is already mapped */
|
/* Check if P5E is already mapped */
|
||||||
if(!MM::Paging::PteValid(PointerP5e))
|
if(!MM::Paging::PteValid(PointerP5e))
|
||||||
{
|
{
|
||||||
/* Map P5E */
|
/* Attempt to allocate a physical page from the PFN database */
|
||||||
MM::Paging::SetPte(TemplateP5e, MM::Pfn::AllocateBootstrapPages(1), 0);
|
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;
|
*PointerP5e = *TemplateP5e;
|
||||||
|
|
||||||
/* Clear the page table */
|
/* Clear the page table */
|
||||||
@@ -223,6 +234,7 @@ MM::Pte::MapPPE(IN PVOID StartAddress,
|
|||||||
IN PMMPPE TemplatePpe)
|
IN PMMPPE TemplatePpe)
|
||||||
{
|
{
|
||||||
PMMPPE EndSpace, PointerPpe;
|
PMMPPE EndSpace, PointerPpe;
|
||||||
|
PFN_NUMBER PageFrameNumber;
|
||||||
|
|
||||||
/* Get PPE addresses */
|
/* Get PPE addresses */
|
||||||
PointerPpe = MM::Paging::GetPpeAddress(StartAddress);
|
PointerPpe = MM::Paging::GetPpeAddress(StartAddress);
|
||||||
@@ -234,8 +246,18 @@ MM::Pte::MapPPE(IN PVOID StartAddress,
|
|||||||
/* Check if PPE is already mapped */
|
/* Check if PPE is already mapped */
|
||||||
if(!MM::Paging::PteValid(PointerPpe))
|
if(!MM::Paging::PteValid(PointerPpe))
|
||||||
{
|
{
|
||||||
/* Map PPE */
|
/* Attempt to allocate a physical page from the PFN database */
|
||||||
MM::Paging::SetPte(TemplatePpe, MM::Pfn::AllocateBootstrapPages(1), 0);
|
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;
|
*PointerPpe = *TemplatePpe;
|
||||||
|
|
||||||
/* Clear the page table */
|
/* Clear the page table */
|
||||||
@@ -270,6 +292,7 @@ MM::Pte::MapPXE(IN PVOID StartAddress,
|
|||||||
IN PMMPXE TemplatePxe)
|
IN PMMPXE TemplatePxe)
|
||||||
{
|
{
|
||||||
PMMPXE EndSpace, PointerPxe;
|
PMMPXE EndSpace, PointerPxe;
|
||||||
|
PFN_NUMBER PageFrameNumber;
|
||||||
|
|
||||||
/* Get PXE addresses */
|
/* Get PXE addresses */
|
||||||
PointerPxe = MM::Paging::GetPxeAddress(StartAddress);
|
PointerPxe = MM::Paging::GetPxeAddress(StartAddress);
|
||||||
@@ -281,8 +304,18 @@ MM::Pte::MapPXE(IN PVOID StartAddress,
|
|||||||
/* Check if PTE is already mapped */
|
/* Check if PTE is already mapped */
|
||||||
if(!MM::Paging::PteValid(PointerPxe))
|
if(!MM::Paging::PteValid(PointerPxe))
|
||||||
{
|
{
|
||||||
/* Map PTE */
|
/* Attempt to allocate a physical page from the PFN database */
|
||||||
MM::Paging::SetPte(TemplatePxe, MM::Pfn::AllocateBootstrapPages(1), 0);
|
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;
|
*PointerPxe = *TemplatePxe;
|
||||||
|
|
||||||
/* Clear the page table */
|
/* Clear the page table */
|
||||||
|
|||||||
@@ -60,6 +60,12 @@ LOADER_MEMORY_DESCRIPTOR MM::HardwarePool::HardwareAllocationDescriptors[MM_HARD
|
|||||||
/* Live address of kernel's hardware heap */
|
/* Live address of kernel's hardware heap */
|
||||||
PVOID MM::HardwarePool::HardwareHeapStart = MM_HARDWARE_HEAP_START_ADDRESS;
|
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 */
|
/* Number of used hardware allocation descriptors */
|
||||||
ULONG MM::HardwarePool::UsedHardwareAllocationDescriptors = 0;
|
ULONG MM::HardwarePool::UsedHardwareAllocationDescriptors = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
* Allocates a physical page in low memory (addressable in real-mode) and maps it into the virtual address space.
|
||||||
*
|
*
|
||||||
* @param MemoryAddress
|
* @param PhysicalAddress
|
||||||
* Supplies a pointer to a variable that receives the identity-mapped virtual address of the allocated memory.
|
* 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.
|
* @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
|
XTAPI
|
||||||
XTSTATUS
|
XTSTATUS
|
||||||
MM::HardwarePool::AllocateRealModeMemory(IN PFN_NUMBER PageCount,
|
MM::HardwarePool::AllocateLowMemory(OUT PPHYSICAL_ADDRESS PhysicalAddress,
|
||||||
OUT PVOID *MemoryAddress)
|
OUT PVOID *VirtualAddress)
|
||||||
{
|
{
|
||||||
PHYSICAL_ADDRESS PhysicalAddress;
|
ULONG AllocationPages, TrampolineCodeSize;
|
||||||
PFN_NUMBER PageFrameNumber;
|
PVOID TrampolineCode;
|
||||||
PVOID VirtualAddress;
|
|
||||||
XTSTATUS Status;
|
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 */
|
/* Allocate physical memory in first 1MB */
|
||||||
Status = AllocateHardwareMemory(PageCount, TRUE, 0x100000, &PhysicalAddress);
|
Status = AllocateHardwareMemory(AllocationPages, TRUE, 0x100000, &LowMemoryPhysicalAddress);
|
||||||
if(Status != STATUS_SUCCESS)
|
if(Status != STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
/* Failed to allocate memory, return error */
|
/* Failed to allocate memory, return error */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate virtual address and page frame number */
|
/* Map the memory to the virtual address */
|
||||||
VirtualAddress = (PVOID)(ULONG_PTR)PhysicalAddress.QuadPart;
|
Status = MapHardwareMemory(LowMemoryPhysicalAddress, AllocationPages, FALSE, &LowMemoryVirtualAddress);
|
||||||
PageFrameNumber = PhysicalAddress.QuadPart >> MM_PAGE_SHIFT;
|
|
||||||
|
|
||||||
/* Identity map the memory to the virtual address */
|
|
||||||
Status = MM::Paging::MapVirtualAddress(VirtualAddress, PageFrameNumber, MM_PTE_EXECUTE_READWRITE);
|
|
||||||
if(Status != STATUS_SUCCESS)
|
if(Status != STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
/* Failed to map memory, return error */
|
/* Failed to map memory, free memory and return error */
|
||||||
|
FreeHardwareMemory(LowMemoryPhysicalAddress, AllocationPages);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the trampoline virtual address and return success */
|
/* Check if the caller requested the allocated addresses */
|
||||||
*MemoryAddress = VirtualAddress;
|
if(PhysicalAddress != NULLPTR && VirtualAddress != NULLPTR)
|
||||||
|
{
|
||||||
|
/* Set the trampoline physical and virtual address and return success */
|
||||||
|
*PhysicalAddress = LowMemoryPhysicalAddress;
|
||||||
|
*VirtualAddress = LowMemoryVirtualAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return success */
|
||||||
return STATUS_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.
|
* 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;
|
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.
|
* 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 success */
|
||||||
return STATUS_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))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -232,6 +232,9 @@ XTAPI
|
|||||||
VOID
|
VOID
|
||||||
MM::Manager::InitializeMemoryManager(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 */
|
/* Scan memory descriptors provided by the boot loader */
|
||||||
MM::Pfn::ScanMemoryDescriptors();
|
MM::Pfn::ScanMemoryDescriptors();
|
||||||
|
|
||||||
@@ -256,6 +259,9 @@ MM::Manager::InitializeMemoryManager(VOID)
|
|||||||
/* Initialize page table */
|
/* Initialize page table */
|
||||||
MM::Pte::InitializePageTable();
|
MM::Pte::InitializePageTable();
|
||||||
|
|
||||||
|
/* Initialize PFN database */
|
||||||
|
MM::Pfn::InitializePfnDatabase();
|
||||||
|
|
||||||
/* Initialize system PTE space */
|
/* Initialize system PTE space */
|
||||||
MM::Pte::InitializeSystemPteSpace();
|
MM::Pte::InitializeSystemPteSpace();
|
||||||
|
|
||||||
@@ -265,9 +271,6 @@ MM::Manager::InitializeMemoryManager(VOID)
|
|||||||
/* Initialize non-paged pool */
|
/* Initialize non-paged pool */
|
||||||
MM::Pool::InitializeNonPagedPool();
|
MM::Pool::InitializeNonPagedPool();
|
||||||
|
|
||||||
/* Initialize PFN database */
|
|
||||||
MM::Pfn::InitializePfnDatabase();
|
|
||||||
|
|
||||||
/* Initialize allocations tracking tables */
|
/* Initialize allocations tracking tables */
|
||||||
MM::Allocator::InitializeAllocationsTracking();
|
MM::Allocator::InitializeAllocationsTracking();
|
||||||
MM::Allocator::InitializeBigAllocationsTracking();
|
MM::Allocator::InitializeBigAllocationsTracking();
|
||||||
|
|||||||
@@ -242,6 +242,7 @@ MM::Pte::MapPDE(IN PVOID StartAddress,
|
|||||||
IN PMMPDE TemplatePde)
|
IN PMMPDE TemplatePde)
|
||||||
{
|
{
|
||||||
PMMPDE EndSpace, PointerPde;
|
PMMPDE EndSpace, PointerPde;
|
||||||
|
PFN_NUMBER PageFrameNumber;
|
||||||
|
|
||||||
/* Get PDE addresses */
|
/* Get PDE addresses */
|
||||||
PointerPde = MM::Paging::GetPdeAddress(StartAddress);
|
PointerPde = MM::Paging::GetPdeAddress(StartAddress);
|
||||||
@@ -253,8 +254,18 @@ MM::Pte::MapPDE(IN PVOID StartAddress,
|
|||||||
/* Check if PDE is already mapped */
|
/* Check if PDE is already mapped */
|
||||||
if(!MM::Paging::PteValid(PointerPde))
|
if(!MM::Paging::PteValid(PointerPde))
|
||||||
{
|
{
|
||||||
/* Map PDE */
|
/* Attempt to allocate a physical page from the PFN database */
|
||||||
MM::Paging::SetPte(TemplatePde, MM::Pfn::AllocateBootstrapPages(1), 0);
|
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);
|
MM::Paging::WritePte(PointerPde, *TemplatePde);
|
||||||
|
|
||||||
/* Clear the page table */
|
/* Clear the page table */
|
||||||
@@ -289,6 +300,7 @@ MM::Pte::MapPTE(IN PVOID StartAddress,
|
|||||||
IN PMMPTE TemplatePte)
|
IN PMMPTE TemplatePte)
|
||||||
{
|
{
|
||||||
PMMPTE EndSpace, PointerPte;
|
PMMPTE EndSpace, PointerPte;
|
||||||
|
PFN_NUMBER PageFrameNumber;
|
||||||
|
|
||||||
/* Get PTE addresses */
|
/* Get PTE addresses */
|
||||||
PointerPte = MM::Paging::GetPteAddress(StartAddress);
|
PointerPte = MM::Paging::GetPteAddress(StartAddress);
|
||||||
@@ -300,8 +312,18 @@ MM::Pte::MapPTE(IN PVOID StartAddress,
|
|||||||
/* Check if PTE is already mapped */
|
/* Check if PTE is already mapped */
|
||||||
if(!MM::Paging::PteValid(PointerPte))
|
if(!MM::Paging::PteValid(PointerPte))
|
||||||
{
|
{
|
||||||
/* Map PTE */
|
/* Attempt to allocate a physical page from the PFN database */
|
||||||
MM::Paging::SetPte(TemplatePte, MM::Pfn::AllocateBootstrapPages(1), 0);
|
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);
|
MM::Paging::WritePte(PointerPte, *TemplatePte);
|
||||||
|
|
||||||
/* Clear the page table */
|
/* Clear the page table */
|
||||||
@@ -313,7 +335,6 @@ MM::Pte::MapPTE(IN PVOID StartAddress,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Releases a block of system PTEs into a specified pool.
|
* Releases a block of system PTEs into a specified pool.
|
||||||
*
|
*
|
||||||
|
|||||||
51
xtoskrnl/ps/process.cc
Normal file
51
xtoskrnl/ps/process.cc
Normal 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
63
xtoskrnl/ps/thread.cc
Normal 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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user