/** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/hl/x86/cpu.c * DESCRIPTION: HAL x86 (i686/AMD64) processor support * DEVELOPERS: Rafal Kupiec */ #include /** * Initializes the processor. * * @param CpuNumber * Supplies the number of the CPU, that is being initialized. * * @return This routine does not return any value. * * @since XT 1.0 */ XTAPI VOID HlInitializeProcessor(VOID) { PKPROCESSOR_BLOCK ProcessorBlock; KAFFINITY Affinity; /* Get current processor block */ ProcessorBlock = KeGetCurrentProcessorBlock(); /* Set initial stall factor, CPU number and mask interrupts */ ProcessorBlock->StallScaleFactor = INITIAL_STALL_FACTOR; ProcessorBlock->Idr = 0xFFFFFFFF; /* Set processor affinity */ Affinity = (KAFFINITY) 1 << ProcessorBlock->CpuNumber; /* Apply affinity to a set of processors */ HlpActiveProcessors |= Affinity; /* Initialize APIC for this processor */ HlpInitializePic(); /* 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; }