diff --git a/sdk/xtdk/amd64/hltypes.h b/sdk/xtdk/amd64/hltypes.h index 4c57ae2..92fd90f 100644 --- a/sdk/xtdk/amd64/hltypes.h +++ b/sdk/xtdk/amd64/hltypes.h @@ -51,6 +51,12 @@ #define APIC_DM_INIT 0x00000500 #define APIC_DM_STARTUP 0x00000600 #define APIC_DM_EXTINT 0x00000700 +#define APIC_DM_ASSERT 0x00004000 +#define APIC_DM_LEVEL 0x00008000 +#define APIC_DM_BROADCAST 0x00080000 + +/* APIC delivery status */ +#define APIC_DELIVERY_PENDING 0x00001000 /* APIC trigger modes */ #define APIC_TGM_EDGE 0 diff --git a/sdk/xtdk/i686/hltypes.h b/sdk/xtdk/i686/hltypes.h index 440976b..defdfc6 100644 --- a/sdk/xtdk/i686/hltypes.h +++ b/sdk/xtdk/i686/hltypes.h @@ -56,6 +56,12 @@ #define APIC_DM_INIT 0x00000500 #define APIC_DM_STARTUP 0x00000600 #define APIC_DM_EXTINT 0x00000700 +#define APIC_DM_ASSERT 0x00004000 +#define APIC_DM_LEVEL 0x00008000 +#define APIC_DM_BROADCAST 0x00080000 + +/* APIC delivery status */ +#define APIC_DELIVERY_PENDING 0x00001000 /* APIC trigger modes */ #define APIC_TGM_EDGE 0 diff --git a/xtoskrnl/hl/x86/cpu.c b/xtoskrnl/hl/x86/cpu.c index 65f321f..7aff72d 100644 --- a/xtoskrnl/hl/x86/cpu.c +++ b/xtoskrnl/hl/x86/cpu.c @@ -45,3 +45,36 @@ HlInitializeProcessor(VOID) /* Set the APIC running level */ HlSetRunLevel(KeGetCurrentProcessorBlock()->RunLevel); } + +XTAPI +XTSTATUS +HlStartProcessor(IN ULONG CpuId, + IN PHYSICAL_ADDRESS EntryPoint) +{ + ULONG Attempt; + + /* Wait until command register is clear */ + while((HlReadApicRegister(APIC_ICR0) & APIC_DELIVERY_PENDING) != 0); + + /* Trigger INIT IPI and wait for delivery bit to be cleared */ + HlpSendIpi(CpuId, APIC_DM_INIT | APIC_DM_LEVEL | APIC_DM_ASSERT); + while((HlReadApicRegister(APIC_ICR0) & APIC_DELIVERY_PENDING) != 0); + + /* Deassert INIT IPI to take CPU out of reset and wait for delivery bit to be cleared */ + HlpSendIpi(CpuId, APIC_DM_INIT | APIC_DM_LEVEL); + while((HlReadApicRegister(APIC_ICR0) & APIC_DELIVERY_PENDING) != 0); + + /* Two attempts to send STARTUP IPI */ + for(Attempt = 0; Attempt < 2; Attempt++) + { + /* Trigger STARTUP IPI and wait for delivery bit to be cleared */ + HlpSendIpi(CpuId, APIC_DM_STARTUP | (EntryPoint.LowPart >> 12)); + while((HlReadApicRegister(APIC_ICR0) & APIC_DELIVERY_PENDING) != 0); + } + + /* Memory barrier */ + ArMemoryBarrier(); + + /* Return success */ + return STATUS_SUCCESS; +} diff --git a/xtoskrnl/includes/amd64/ari.h b/xtoskrnl/includes/amd64/ari.h index 1b63daa..7e9a1b2 100644 --- a/xtoskrnl/includes/amd64/ari.h +++ b/xtoskrnl/includes/amd64/ari.h @@ -117,6 +117,10 @@ XTCDECL VOID ArSetInterruptFlag(VOID); +XTCDECL +VOID +ArStartApplicationProcessor(); + XTCDECL VOID ArStoreGlobalDescriptorTable(OUT PVOID Destination); diff --git a/xtoskrnl/includes/i686/ari.h b/xtoskrnl/includes/i686/ari.h index 377e7f3..5009b76 100644 --- a/xtoskrnl/includes/i686/ari.h +++ b/xtoskrnl/includes/i686/ari.h @@ -113,6 +113,10 @@ XTCDECL VOID ArSetInterruptFlag(VOID); +XTCDECL +VOID +ArStartApplicationProcessor(); + XTCDECL VOID ArStoreGlobalDescriptorTable(OUT PVOID Destination);