Esempio n. 1
0
// Start additional processor running bootstrap code at addr.
// See Appendix B of MultiProcessor Specification.
void
lapic_startap(uint8_t apicid, uint32_t addr)
{
	int i;
	uint16_t *wrv;
  
	// "The BSP must initialize CMOS shutdown code to 0AH
	// and the warm reset vector (DWORD based at 40:67) to point at
	// the AP startup code prior to the [universal startup algorithm]."
	outb(IO_RTC, 0xF);  // offset 0xF is shutdown code
	outb(IO_RTC+1, 0x0A);
	wrv = (uint16_t *)RELOC(0x40<<4 | 0x67);  // Warm reset vector
	wrv[0] = 0;
	wrv[1] = addr >> 4;

	// "Universal startup algorithm."
	// Send INIT (level-triggered) interrupt to reset other CPU.
	lapic_write(ICRHI, apicid<<ID_SHIFT);
	lapic_write(ICRLO, DLMODE_INIT | LEVEL | ASSERT);
	microdelay(200);
	lapic_write(ICRLO, DLMODE_INIT | LEVEL);
	microdelay(100);	// should be 10ms, but too slow in Bochs!
	// Send startup IPI (twice!) to enter bootstrap code.
	// Regular hardware is supposed to only accept a STARTUP
	// when it is in the halted state due to an INIT.  So the second
	// should be ignored, but it is part of the official Intel algorithm.
	// Bochs complains about the second one.  Too bad for Bochs.
	for(i = 0; i < 2; i++){
		lapic_write(ICRHI, apicid<<24);
		lapic_write(ICRLO, DLMODE_STARTUP | (addr>>12));
		microdelay(200);
	}
}
Esempio n. 2
0
/* Send IPI to dedicated CPU 
 * Success: 0
 * Failure: < 0
 */
int
lapic_ipi(uint32_t cp_id, uint32_t ino)
{
    lapic_write(ICRHI, cp_id << ID_SHIFT);
    lapic_write(ICRLO, DLMODE_FIXED | DEASSERT | ino);
    return lapic_icr_wait();
}
Esempio n. 3
0
static void init_timer(void)
{
	/* Set the apic timer to no interrupts and periodic mode */
	lapic_write(LAPIC_LVTT, (1 << 17)|(1<< 16)|(0 << 12)|(0 << 0));

	/* Set the divider to 1, no divider */
	lapic_write(LAPIC_TDCR, LAPIC_TDR_DIV_1);

	/* Set the initial counter to 0xffffffff */
	lapic_write(LAPIC_TMICT, 0xffffffff);
}
Esempio n. 4
0
void init_timer(void)
{
	/* Set the apic timer to no interrupts and periodic mode */
	lapic_write(LAPIC_LVTT, (LAPIC_LVT_TIMER_PERIODIC | LAPIC_LVT_MASKED));

	/* Set the divider to 1, no divider */
	lapic_write(LAPIC_TDCR, LAPIC_TDR_DIV_1);

	/* Set the initial counter to 0xffffffff */
	lapic_write(LAPIC_TMICT, 0xffffffff);

	/* Set FSB frequency to a reasonable value */
	set_timer_fsb();
}
Esempio n. 5
0
File: hvmloader.c Progetto: CPFL/xen
static void apic_setup(void)
{
    /* Set the IOAPIC ID to the static value used in the MP/ACPI tables. */
    ioapic_write(0x00, IOAPIC_ID);

    /* NMIs are delivered direct to the BSP. */
    lapic_write(APIC_SPIV, APIC_SPIV_APIC_ENABLED | 0xFF);
    lapic_write(APIC_LVT0, (APIC_MODE_EXTINT << 8) | APIC_LVT_MASKED);
    lapic_write(APIC_LVT1, APIC_MODE_NMI << 8);

    /* 8259A ExtInts are delivered through IOAPIC pin 0 (Virtual Wire Mode). */
    ioapic_write(0x10, APIC_DM_EXTINT);
    ioapic_write(0x11, SET_APIC_ID(LAPIC_ID(0)));
}
Esempio n. 6
0
/* Broadcast IPI to CPUs
 * Success: 0
 * Failure: < 0
 */
int
lapic_broadcast(int self, uint32_t ino)
{
    uint32_t flag = self ? DEST_ALLINCL : DEST_ALLEXCL;
    flag |= ino == T_NMI ? DLMODE_NMI : 0;
    lapic_write(ICRLO, flag | DEASSERT | DLMODE_FIXED | ino);
    return lapic_icr_wait();
}
Esempio n. 7
0
File: apic.c Progetto: glguida/mh
void lapic_configure(void)
{
	unsigned i, physid = lapic_getcurrent();
	struct lapic_desc *d = NULL;

	for (i = 0; i < lapics_no; i++) {
		if (lapics[i].physid == physid)
			d = lapics + i;
	}
	if (d == NULL) {
		printf("Warning: Current CPU not in Platform Tables!\n");
		/* Try to continue, ignore the NMI configuration */
	} else {
		lapic_write(L_LVT_LINT(0), d->lint[0]);
		lapic_write(L_LVT_LINT(1), d->lint[1]);
	}
	/* Enable LAPIC */
	lapic_write(L_MISC, lapic_read(L_MISC) | 0x100);
}
Esempio n. 8
0
File: smp.c Progetto: 0day-ci/xen
static void boot_cpu(unsigned int cpu)
{
    unsigned int icr2 = SET_APIC_DEST_FIELD(LAPIC_ID(cpu));

    /* Initialise shared variables. */
    ap_cpuid = cpu;
    ap_callin = 0;
    wmb();

    /* Wake up the secondary processor: INIT-SIPI-SIPI... */
    lapic_wait_ready();
    lapic_write(APIC_ICR2, icr2);
    lapic_write(APIC_ICR, APIC_DM_INIT);
    lapic_wait_ready();
    lapic_write(APIC_ICR2, icr2);
    lapic_write(APIC_ICR, APIC_DM_STARTUP | (AP_BOOT_EIP >> 12));
    lapic_wait_ready();
    lapic_write(APIC_ICR2, icr2);
    lapic_write(APIC_ICR, APIC_DM_STARTUP | (AP_BOOT_EIP >> 12));
    lapic_wait_ready();

    /*
     * Wait for the secondary processor to complete initialisation.
     * Do not touch shared resources meanwhile.
     */
    while ( !ap_callin )
        cpu_relax();

    /* Take the secondary processor offline. */
    lapic_write(APIC_ICR2, icr2);
    lapic_write(APIC_ICR, APIC_DM_INIT);
    lapic_wait_ready();    
}
Esempio n. 9
0
static void apic_setup(void)
{
    /*
     * This would the The Right Thing To Do (tm), if only qemu negotiated
     * with Xen where the IO-APIC actually sits (which is currently hard
     * coded in Xen and can't be controlled externally). Uncomment this code
     * once that changed.
    ioapic_base_address |= (pci_readb(PCI_ISA_DEVFN, 0x80) & 0x3f) << 10;
     */
    ioapic_version = ioapic_read(0x01) & 0xff;

    /* Set the IOAPIC ID to the static value used in the MP/ACPI tables. */
    ioapic_write(0x00, IOAPIC_ID);

    /* NMIs are delivered direct to the BSP. */
    lapic_write(APIC_SPIV, APIC_SPIV_APIC_ENABLED | 0xFF);
    lapic_write(APIC_LVT0, (APIC_MODE_EXTINT << 8) | APIC_LVT_MASKED);
    lapic_write(APIC_LVT1, APIC_MODE_NMI << 8);

    /* 8259A ExtInts are delivered through IOAPIC pin 0 (Virtual Wire Mode). */
    ioapic_write(0x10, APIC_DM_EXTINT);
    ioapic_write(0x11, SET_APIC_ID(LAPIC_ID(0)));
}
Esempio n. 10
0
static int start_aps(int ap_count, atomic_t *num_aps)
{
	int sipi_vector;
	/* Max location is 4KiB below 1MiB */
	const int max_vector_loc = ((1 << 20) - (1 << 12)) >> 12;

	if (ap_count == 0)
		return 0;

	/* The vector is sent as a 4k aligned address in one byte */
	sipi_vector = AP_DEFAULT_BASE >> 12;

	if (sipi_vector > max_vector_loc) {
		printf("SIPI vector too large! 0x%08x\n",
		       sipi_vector);
		return -1;
	}

	debug("Attempting to start %d APs\n", ap_count);

	if ((lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY)) {
		debug("Waiting for ICR not to be busy...");
		if (apic_wait_timeout(1000, 50)) {
			debug("timed out. Aborting.\n");
			return -1;
		} else {
			debug("done.\n");
		}
	}

	/* Send INIT IPI to all but self */
	lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
	lapic_write(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
		    LAPIC_DM_INIT);
	debug("Waiting for 10ms after sending INIT.\n");
	mdelay(10);

	/* Send 1st SIPI */
	if ((lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY)) {
		debug("Waiting for ICR not to be busy...");
		if (apic_wait_timeout(1000, 50)) {
			debug("timed out. Aborting.\n");
			return -1;
		} else {
			debug("done.\n");
		}
	}

	lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
	lapic_write(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
		    LAPIC_DM_STARTUP | sipi_vector);
	debug("Waiting for 1st SIPI to complete...");
	if (apic_wait_timeout(10000, 50)) {
		debug("timed out.\n");
		return -1;
	} else {
		debug("done.\n");
	}

	/* Wait for CPUs to check in up to 200 us */
	wait_for_aps(num_aps, ap_count, 200, 15);

	/* Send 2nd SIPI */
	if ((lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY)) {
		debug("Waiting for ICR not to be busy...");
		if (apic_wait_timeout(1000, 50)) {
			debug("timed out. Aborting.\n");
			return -1;
		} else {
			debug("done.\n");
		}
	}

	lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
	lapic_write(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
		    LAPIC_DM_STARTUP | sipi_vector);
	debug("Waiting for 2nd SIPI to complete...");
	if (apic_wait_timeout(10000, 50)) {
		debug("timed out.\n");
		return -1;
	} else {
		debug("done.\n");
	}

	/* Wait for CPUs to check in */
	if (wait_for_aps(num_aps, ap_count, 10000, 50)) {
		debug("Not all APs checked in: %d/%d.\n",
		      atomic_read(num_aps), ap_count);
		return -1;
	}

	return 0;
}
Esempio n. 11
0
static  void
lapic_eoi(void){

	lapic_write(LAPIC_EOI, 0);
	return;
}
Esempio n. 12
0
static  uint32_t
lapic_errstatus(void){

	lapic_write(LAPIC_ESR, 0);
	return lapic_read(LAPIC_ESR);
}
Esempio n. 13
0
static int lapic_start_cpu(unsigned long apicid)
{
	int timeout;
	unsigned long send_status, accept_status;
	int j, maxlvt;

	/*
	 * Starting actual IPI sequence...
	 */

	printk(BIOS_SPEW, "Asserting INIT.\n");

	/*
	 * Turn INIT on target chip
	 */
	lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));

	/*
	 * Send IPI
	 */

	lapic_write_around(LAPIC_ICR, LAPIC_INT_LEVELTRIG | LAPIC_INT_ASSERT
				| LAPIC_DM_INIT);

	printk(BIOS_SPEW, "Waiting for send to finish...\n");
	timeout = 0;
	do {
		printk(BIOS_SPEW, "+");
		udelay(100);
		send_status = lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY;
	} while (send_status && (timeout++ < 1000));
	if (timeout >= 1000) {
		printk(BIOS_ERR, "CPU %ld: First APIC write timed out. "
			"Disabling\n", apicid);
		// too bad.
		printk(BIOS_ERR, "ESR is 0x%lx\n", lapic_read(LAPIC_ESR));
		if (lapic_read(LAPIC_ESR)) {
			printk(BIOS_ERR, "Try to reset ESR\n");
			lapic_write_around(LAPIC_ESR, 0);
			printk(BIOS_ERR, "ESR is 0x%lx\n",
				lapic_read(LAPIC_ESR));
		}
		return 0;
	}
#if !IS_ENABLED(CONFIG_CPU_AMD_MODEL_10XXX) \
	&& !IS_ENABLED(CONFIG_CPU_INTEL_MODEL_206AX) \
	&& !IS_ENABLED(CONFIG_CPU_INTEL_MODEL_2065X)
	mdelay(10);
#endif

	printk(BIOS_SPEW, "Deasserting INIT.\n");

	/* Target chip */
	lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));

	/* Send IPI */
	lapic_write_around(LAPIC_ICR, LAPIC_INT_LEVELTRIG | LAPIC_DM_INIT);

	printk(BIOS_SPEW, "Waiting for send to finish...\n");
	timeout = 0;
	do {
		printk(BIOS_SPEW, "+");
		udelay(100);
		send_status = lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY;
	} while (send_status && (timeout++ < 1000));
	if (timeout >= 1000) {
		printk(BIOS_ERR, "CPU %ld: Second APIC write timed out. "
			"Disabling\n", apicid);
		// too bad.
		return 0;
	}

	/*
	 * Run STARTUP IPI loop.
	 */
	printk(BIOS_SPEW, "#startup loops: %d.\n", CONFIG_NUM_IPI_STARTS);

	maxlvt = 4;

	for (j = 1; j <= CONFIG_NUM_IPI_STARTS; j++) {
		printk(BIOS_SPEW, "Sending STARTUP #%d to %lu.\n", j, apicid);
		lapic_read_around(LAPIC_SPIV);
		lapic_write(LAPIC_ESR, 0);
		lapic_read(LAPIC_ESR);
		printk(BIOS_SPEW, "After apic_write.\n");

		/*
		 * STARTUP IPI
		 */

		/* Target chip */
		lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));

		/* Boot on the stack */
		/* Kick the second */
		lapic_write_around(LAPIC_ICR, LAPIC_DM_STARTUP
					| (AP_SIPI_VECTOR >> 12));

		/*
		 * Give the other CPU some time to accept the IPI.
		 */
		udelay(300);

		printk(BIOS_SPEW, "Startup point 1.\n");

		printk(BIOS_SPEW, "Waiting for send to finish...\n");
		timeout = 0;
		do {
			printk(BIOS_SPEW, "+");
			udelay(100);
			send_status = lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY;
		} while (send_status && (timeout++ < 1000));

		/*
		 * Give the other CPU some time to accept the IPI.
		 */
		udelay(200);
		/*
		 * Due to the Pentium erratum 3AP.
		 */
		if (maxlvt > 3) {
			lapic_read_around(LAPIC_SPIV);
			lapic_write(LAPIC_ESR, 0);
		}
		accept_status = (lapic_read(LAPIC_ESR) & 0xEF);
		if (send_status || accept_status)
			break;
	}
	printk(BIOS_SPEW, "After Startup.\n");
	if (send_status)
		printk(BIOS_WARNING, "APIC never delivered???\n");
	if (accept_status)
		printk(BIOS_WARNING, "APIC delivery error (%lx).\n",
			accept_status);
	if (send_status || accept_status)
		return 0;
	return 1;
}
Esempio n. 14
0
void
lapic_init(int c)
{
	uint32_t edx;

	
	if(!lapic) 
		return;
	/* Check if APIC is supported */
	cpuid(0x01, 0, 0, 0, &edx);
	if (!(edx & 0x200))
		return;

	if (c == mp_bcpu()){
			pte_t *pte;
			pte = pgdir_walk(boot_pgdir, (void *)lapic, 1);
			*pte = (physaddr_t)lapic | PTE_W | PTE_P | PTE_PCD; /* Must be Strong Uncacheable */
		}
	// Enable local APIC; set spurious interrupt vector.
	lapic_write(SVR, ENABLE | (IRQ_OFFSET+IRQ_SPURIOUS));

	// The timer repeatedly counts down at bus frequency
	// from lapic[TICR] and then issues an interrupt.  
	lapic_write(TDCR, X1);
	lapic_write(TIMER, PERIODIC | (IRQ_OFFSET + IRQ_TIMER));
	lapic_write(TICR, 10000000); 

	/* Linux uses if () way -_-, but I'd like IOAPIC to distribute ExtINT
	 */
	if (0) {//(c == mp_bcpu()) {
		lapic_write(LINT0, DLMODE_EXTINT);
		lapic_write(LINT1, DLMODE_NMI);
	} else {
		lapic_write(LINT0, MASKED);
		lapic_write(LINT1, MASKED);
	}

	// Disable performance counter overflow interrupts
	// on machines that provide that interrupt entry.
	if(((lapic[VER]>>16) & 0xFF) >= 4)
		lapic_write(PCINT, MASKED);

	// Map error interrupt to IRQ_ERROR.
	lapic_write(ERROR, IRQ_OFFSET+IRQ_ERROR);

	// Clear error status register (requires back-to-back writes).
	lapic_write(ESR, 0);
	lapic_write(ESR, 0);

	// Ack any outstanding interrupts.
	lapic_write(EOI, 0);

	// Send an Init Level De-Assert to synchronise arbitration ID's.
	lapic_write(ICRHI, 0);
	lapic_write(ICRLO, BCAST | DLMODE_INIT | LEVEL);
	while(lapic[ICRLO] & DELIVS)
		;

	// Enable interrupts on the APIC (but not on the processor).
	lapic_write(TPR, 0);	/* 0: Handle all interrupts
				 * 15: Interrupts inhibited
				 * P. Vol.3 9-39
				 */
	//cprintf("CPU %x: lapic_int() success\n", c);
}
Esempio n. 15
0
// Acknowledge interrupt.
void
lapic_eoi(void)
{
	if(lapic)
		lapic_write(EOI, 0);
}
Esempio n. 16
0
int lapic_clock_setup(struct time_dev_conf *conf) {
	static int initialized = 0;
	uint32_t ticks, cpubusfreq, counter;
	uint8_t tmp;

	if (initialized) {
		return ENOERR;
	}
	initialized = 1;

	/*
	 * Map APIC timer to an interrupt, and by that enable it in
	 * one-shot mode.
	 */
	lapic_write(LAPIC_LVT_TR, 32);

	/* Set up divide value to 16 */
	lapic_write(LAPIC_TIMER_DCR, 0x03);

	/*
	 * Initialize PIT Ch 2 in one-shot mode.
	 * Waiting 1/100 sec.
	 */
	outb((inb(0x61) & 0xFD) | 1, 0x61);
	outb(0xB2, 0x43);

	/* 1193180/100 Hz = 11931 = 2e9bh */
	outb(0x9B, 0x42);	/* LSB */
	inb(0x60);	/* short delay */
	outb(0x2E, 0x42);	/* MSB */

	/* Reset PIT one-shot counter (start counting) */
	tmp = inb(0x61) & 0xFE;
	outb((uint8_t) tmp, 0x61);     /* Gate low */
	outb((uint8_t) tmp | 1, 0x61); /* Gate high */

	/* Reset APIC timer (set counter to -1) */
	lapic_write(LAPIC_TIMER_ICR, 0xFFFFFFFF);

	/* Now wait until PIT counter reaches zero */
	while(!(inb(0x61) & 0x20));

	/* Stop APIC timer */
	lapic_write(LAPIC_LVT_TR, 0x10000);

	/* Now do the math... */
	ticks = (0xFFFFFFFF - lapic_read(LAPIC_TIMER_CCR)) + 1;
	cpubusfreq = ticks * 16 * 100;
	counter = cpubusfreq / LAPIC_HZ / 16;

	/* Set APIC timer counter initializer */
	lapic_write(LAPIC_TIMER_ICR, counter < 16 ? 16 : counter);

	/* Finally re-enable timer in periodic mode. */
	lapic_write(LAPIC_LVT_TR, 32 | 0x20000);

#if 0
	/*
	 * Setting divide value register again not needed by the manuals
	 * although I have found buggy hardware that required it
	 */
	lapic_write(LAPIC_TIMER_DCR, 0x03);
#endif

	return ENOERR;
}