Пример #1
0
OsStatus_t
ApicPerformIPI(
    _In_ UUId_t CoreId,
    _In_ int    Assert)
{
	uint32_t    IpiHigh = APIC_DESTINATION(CoreId); // We use physical addressing for IPI/SIPI
	uint32_t    IpiLow  = 0;
    IntStatus_t InterruptStatus;
    OsStatus_t  Status;

    // Determine assert or deassert
    if (Assert) {
        IpiLow = APIC_DELIVERY_MODE(APIC_MODE_INIT) | APIC_LEVEL_ASSERT | APIC_DESTINATION_PHYSICAL;
    }
    else {
        IpiLow = APIC_DELIVERY_MODE(APIC_MODE_INIT) | APIC_TRIGGER_LEVEL | APIC_DESTINATION_PHYSICAL;
    }
    
	// Wait for ICR to clear
    InterruptStatus = InterruptDisable();
	Status          = ApicWaitForIdle();
    if (Status == OsSuccess) {        
        // Always write upper first, irq is sent when low is written
        ApicWriteLocal(APIC_ICR_HIGH, IpiHigh);
        ApicWriteLocal(APIC_ICR_LOW,  IpiLow);
        Status = ApicWaitForIdle(); 
    }
    InterruptRestoreState(InterruptStatus);
    return Status;
}
Пример #2
0
OsStatus_t
ApicPerformSIPI(
    _In_ UUId_t    CoreId,
    _In_ uintptr_t Address)
{
	uint32_t    IpiLow  = APIC_DELIVERY_MODE(APIC_MODE_SIPI) | APIC_LEVEL_ASSERT | APIC_DESTINATION_PHYSICAL;
	uint32_t    IpiHigh = APIC_DESTINATION(CoreId); // We use physical addressing for IPI/SIPI
    uint8_t     Vector  = 0;
    IntStatus_t InterruptStatus;
    OsStatus_t  Status;
    
    // Sanitize address given
    assert((Address % 0x1000) == 0);
    Vector = Address / 0x1000;
    assert(Vector <= 0xF);
    IpiLow |= Vector;

	// Wait for ICR to clear
    InterruptStatus = InterruptDisable();
	Status          = ApicWaitForIdle();
    if (Status == OsSuccess) {        
        // Always write upper first, irq is sent when low is written
        ApicWriteLocal(APIC_ICR_HIGH, IpiHigh);
        ApicWriteLocal(APIC_ICR_LOW,  IpiLow);
        Status = ApicWaitForIdle();
    }
    InterruptRestoreState(InterruptStatus);
    return Status;
}
Пример #3
0
OsStatus_t
ApicSendInterrupt(
    _In_ InterruptTarget_t  Type,
    _In_ UUId_t             Specific,
    _In_ uint32_t           Vector)
{
	uint32_t    IpiLow  = 0;
	uint32_t    IpiHigh = 0;
    UUId_t      CoreId  = ArchGetProcessorCoreId();
    IntStatus_t InterruptStatus;
    OsStatus_t  Status;

    if (!ApicIsInitialized()) {
        return OsSuccess;
    }
    
    if (Type == InterruptSpecific && Specific == CoreId) {
        Type = InterruptSelf;
    }

    // Handle target types
    if (Type == InterruptSpecific) {
	    IpiHigh = APIC_DESTINATION(Specific);
    }
    else if (Type == InterruptSelf) {
        IpiLow |= (1 << 18);
    }
    else if (Type == InterruptAll) {
        IpiLow |= (1 << 19);
    }
    else {
        IpiLow |= (1 << 19) | (1 << 18);
    }

	// Physical Destination (Bit 11 = 0)
	// Fixed Delivery
	// Assert (Bit 14 = 1)
    // Edge (Bit 15 = 0)
	IpiLow |= APIC_VECTOR(Vector) | APIC_LEVEL_ASSERT | APIC_DESTINATION_PHYSICAL;

    // Are we sending to ourself? Handle this a bit differently, if the ICR is already
    // busy we don't want to clear it as we already a send pending, just queue up interrupt
    InterruptStatus = InterruptDisable();
	Status          = ApicWaitForIdle();
    if (Status == OsSuccess) {
        ApicWriteLocal(APIC_ICR_HIGH, IpiHigh);
        ApicWriteLocal(APIC_ICR_LOW,  IpiLow);
        Status = ApicWaitForIdle();
    }
    InterruptRestoreState(InterruptStatus);
    return Status;
}
Пример #4
0
void
ApicSynchronizeArbIds(void)
{
    // Variables
    IntStatus_t InterruptStatus;
    OsStatus_t Status;

	// Not needed on AMD and not supported on P4 
	// So we need a check here in place to do it @todo
    InterruptStatus = InterruptDisable();
	Status          = ApicWaitForIdle();
    assert(Status != OsError);

	ApicWriteLocal(APIC_ICR_HIGH,   0);
	ApicWriteLocal(APIC_ICR_LOW,    APIC_ICR_SH_ALL | APIC_TRIGGER_LEVEL | APIC_DELIVERY_MODE(APIC_MODE_INIT));
	
    Status = ApicWaitForIdle();
    assert(Status != OsError);
    InterruptRestoreState(InterruptStatus);
}
Пример #5
0
/* The YIELD handler */
int ThreadingYield(void *Args)
{
	/* Get registers */
	Registers_t *Regs = NULL;
	uint32_t TimeSlice = 20;
	uint32_t TaskPriority = 0;
	Cpu_t CurrCpu = ApicGetCpu();

	/* Send EOI */
	ApicSendEoi(0, INTERRUPT_YIELD);

	/* Switch Task */ 
	Regs = _ThreadingSwitch((Registers_t*)Args, 0, &TimeSlice, &TaskPriority);

	/* If we just got hold of idle task, well f**k it disable timer
	* untill we get another task */
	if (!(ThreadingGetCurrentThread(CurrCpu)->Flags & THREADING_IDLE))
	{
		/* Set Task Priority */
		ApicSetTaskPriority(61 - TaskPriority);

		/* Restart timer */
		ApicWriteLocal(APIC_INITIAL_COUNT, GlbTimerQuantum * TimeSlice);
	}
	else
	{
		/* Set low priority */
		ApicSetTaskPriority(0);

		/* Disable timer */
		ApicWriteLocal(APIC_INITIAL_COUNT, 0);
	}

	/* Enter new thread */
	enter_thread(Regs);

	/* Never reached */
	return X86_IRQ_HANDLED;
}