Пример #1
0
void ioapic_route_irq(uint8_t irq, uint8_t dest) {
	
	if (((irq + KERNEL_IRQ_OFFSET) >= NUM_IRQS) || (ioapic_redirects[irq].ioapic_address == NULL)) {
		panic("TRYING TO REROUTE AN INVALID IRQ!");
	}

	// THIS IS A TEMP CHECK. IF WE USE LOGICAL PARTITIONS THIS MUST BE REMOVED
        extern volatile uint32_t num_cpus;
	if (dest >= num_cpus)
		panic("TRYING TO REROUTE TO AN INVALID DESTINATION!");
	
	if (irq == 0 && dest != 0)
		cprintf("WARNING: Rerouting IRQ to core != 0 may cause undefined behavior!\n");

	// Bit pack our redirection entry. This is black magic based on the spec. See the x58 spec.
	uint32_t redirect_low = KERNEL_IRQ_OFFSET + irq;
	redirect_low = redirect_low | (ioapic_redirects[irq].ioapic_flags << 8);
	uint32_t redirect_high = dest << 24;
	
	// YOU MUST MUST MUST MUST MUST MUST MUST write the high bits first. If you don't, you get interrupts going to crazy places
	// Ask Paul about that afternoon of his life.
	write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address , IOAPIC_REDIRECT_OFFSET + 2*ioapic_redirects[irq].ioapic_int + 1);
	write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address  + IOAPIC_WRITE_WINDOW_OFFSET, redirect_high);
	write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address , IOAPIC_REDIRECT_OFFSET + 2*ioapic_redirects[irq].ioapic_int);
	write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address  + IOAPIC_WRITE_WINDOW_OFFSET, redirect_low);
}
Пример #2
0
static void rtblput(struct apic *apic, int sel, uint32_t hi, uint32_t lo)
{
	sel = Ioredtbl + 2 * sel;

	write_mmreg32(apic->addr + Ioregsel, sel + 1);
	write_mmreg32(apic->addr + Iowin, hi);
	write_mmreg32(apic->addr + Ioregsel, sel);
	write_mmreg32(apic->addr + Iowin, lo);
}
Пример #3
0
static void rtblget(struct apic *apic, int sel, uint32_t * hi, uint32_t * lo)
{
	sel = Ioredtbl + 2 * sel;

	write_mmreg32(apic->addr + Ioregsel, sel + 1);
	*hi = read_mmreg32(apic->addr + Iowin);
	write_mmreg32(apic->addr + Ioregsel, sel);
	*lo = read_mmreg32(apic->addr + Iowin);
}
Пример #4
0
/*
 * Sets the LAPIC timer to go off after a certain number of ticks.  The primary
 * clock freq is actually the bus clock, which we figure out during timer_init
 * Unmasking is implied.  Ref SDM, 3A, 9.6.4
 */
void __lapic_set_timer(uint32_t ticks, uint8_t vec, bool periodic, uint8_t div)
{
	// clears bottom bit and then set divider
	write_mmreg32(LAPIC_TIMER_DIVIDE, (read_mmreg32(LAPIC_TIMER_DIVIDE) &~0xf) |
	              (div & 0xf));
	// set LVT with interrupt handling information
	write_mmreg32(LAPIC_LVT_TIMER, vec | (periodic << 17));
	write_mmreg32(LAPIC_TIMER_INIT, ticks);
	// For debugging when we expand this
	//cprintf("LAPIC LVT Timer: 0x%08x\n", read_mmreg32(LAPIC_LVT_TIMER));
	//cprintf("LAPIC Init Count: 0x%08x\n", read_mmreg32(LAPIC_TIMER_INIT));
	//cprintf("LAPIC Current Count: 0x%08x\n", read_mmreg32(LAPIC_TIMER_CURRENT));
}
Пример #5
0
/** @brief Reconfigure the correct IOAPIC to no longer route a given irq to any core
  * 
  * This function will take an irq given by 'irq' and using the interal IOAPIC
  * strucures will adjust the IOAPIC to no longer route that irq to any destination
  *
  * This function must be called after ioapic_init() is called, but need not be called after a matching ioapic_route_irq()
  *
  * There is no notion of success besides invalid data, which casues a panic.
  *
  * @todo Decide on a synchronization mechinism
  * 
  * @param[in] irq 	The IRQ we are trying to unroute. This is non-kernal-offseted. EX: Pit is IRQ 0, not 32.
  */
void ioapic_unroute_irq(uint8_t irq) {

	if (((irq + KERNEL_IRQ_OFFSET) >= NUM_IRQS) || (ioapic_redirects[irq].ioapic_address == NULL)) {
		panic("TRYING TO REROUTE AN INVALID IRQ!");
	}
	
	// Must write low first, else we will reroute to a wrong core for a split before turning off
	write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address , IOAPIC_REDIRECT_OFFSET + 2*ioapic_redirects[irq].ioapic_int);
	write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address  + IOAPIC_WRITE_WINDOW_OFFSET, IOAPIC_UNROUTE_LOW);
	
	write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address , IOAPIC_REDIRECT_OFFSET + 2*ioapic_redirects[irq].ioapic_int + 1);
	write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address  + IOAPIC_WRITE_WINDOW_OFFSET, IOAPIC_UNROUTE_HIGH);

}
Пример #6
0
static void perfmon_arm_irq(void)
{
	write_mmreg32(LAPIC_LVT_PERFMON, IdtLAPIC_PCINT);
}