Exemplo n.º 1
0
void __init sync_Arb_IDs(void)
{
	/* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1 */
	unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR));
	if (ver >= 0x14)	/* P4 or higher */
		return;
	/*
	 * Wait for idle.
	 */
	apic_wait_icr_idle();

	apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n");
	apic_write_around(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG
				| APIC_DM_INIT);
}
Exemplo n.º 2
0
void clear_local_APIC(void)
{
	int maxlvt;
	unsigned int v;

	maxlvt = get_maxlvt();

	/*
	 * Masking an LVT entry on a P6 can trigger a local APIC error
	 * if the vector is zero. Mask LVTERR first to prevent this.
	 */
	if (maxlvt >= 3) {
		v = ERROR_APIC_VECTOR; /* any non-zero vector will do */
		apic_write_around(APIC_LVTERR, v | APIC_LVT_MASKED);
	}
	/*
	 * Careful: we have to set masks only first to deassert
	 * any level-triggered sources.
	 */
	v = apic_read(APIC_LVTT);
	apic_write_around(APIC_LVTT, v | APIC_LVT_MASKED);
	v = apic_read(APIC_LVT0);
	apic_write_around(APIC_LVT0, v | APIC_LVT_MASKED);
	v = apic_read(APIC_LVT1);
	apic_write_around(APIC_LVT1, v | APIC_LVT_MASKED);
	if (maxlvt >= 4) {
		v = apic_read(APIC_LVTPC);
		apic_write_around(APIC_LVTPC, v | APIC_LVT_MASKED);
	}

	/*
	 * Clean APIC state for other OSs:
	 */
	apic_write_around(APIC_LVTT, APIC_LVT_MASKED);
	apic_write_around(APIC_LVT0, APIC_LVT_MASKED);
	apic_write_around(APIC_LVT1, APIC_LVT_MASKED);
	if (maxlvt >= 3)
		apic_write_around(APIC_LVTERR, APIC_LVT_MASKED);
	if (maxlvt >= 4)
		apic_write_around(APIC_LVTPC, APIC_LVT_MASKED);
	v = GET_APIC_VERSION(apic_read(APIC_LVR));
	if (APIC_INTEGRATED(v)) {	/* !82489DX */
		if (maxlvt > 3)
			apic_write(APIC_ESR, 0);
		apic_read(APIC_ESR);
	}
}
Exemplo n.º 3
0
static void __setup_APIC_LVTT(unsigned int clocks)
{
	unsigned int lvtt_value, tmp_value, ver;

	ver = GET_APIC_VERSION(apic_read(APIC_LVR));
	lvtt_value = APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR;
	apic_write_around(APIC_LVTT, lvtt_value);

	/*
	 * Divide PICLK by 16
	 */
	tmp_value = apic_read(APIC_TDCR);
	apic_write_around(APIC_TDCR, (tmp_value
				& ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE))
				| APIC_TDR_DIV_16);

	apic_write_around(APIC_TMICT, clocks/APIC_DIVISOR);
}
Exemplo n.º 4
0
/*
 * An initial setup of the virtual wire mode.
 */
void __init init_bsp_APIC(void)
{
	unsigned long value, ver;

	/*
	 * Don't do the setup now if we have a SMP BIOS as the
	 * through-I/O-APIC virtual wire mode might be active.
	 */
	if (smp_found_config || !cpu_has_apic)
		return;

	value = apic_read(APIC_LVR);
	ver = GET_APIC_VERSION(value);

	/*
	 * Do not trust the local APIC being empty at bootup.
	 */
	clear_local_APIC();

	/*
	 * Enable APIC.
	 */
	value = apic_read(APIC_SPIV);
	value &= ~APIC_VECTOR_MASK;
	value |= APIC_SPIV_APIC_ENABLED;
	
	/* This bit is reserved on P4/Xeon and should be cleared */
	if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && (boot_cpu_data.x86 == 15))
		value &= ~APIC_SPIV_FOCUS_DISABLED;
	else
		value |= APIC_SPIV_FOCUS_DISABLED;
	value |= SPURIOUS_APIC_VECTOR;
	apic_write_around(APIC_SPIV, value);

	/*
	 * Set up the virtual wire mode.
	 */
	apic_write_around(APIC_LVT0, APIC_DM_EXTINT);
	value = APIC_DM_NMI;
	if (!APIC_INTEGRATED(ver))		/* 82489DX */
		value |= APIC_LVT_LEVEL_TRIGGER;
	apic_write_around(APIC_LVT1, value);
}
Exemplo n.º 5
0
int __init verify_local_APIC(void)
{
    unsigned int reg0, reg1;


    reg0 = apic_read(APIC_LVR);
    apic_printk(APIC_DEBUG, "Getting VERSION: %x\n", reg0);
    apic_write(APIC_LVR, reg0 ^ APIC_LVR_MASK);
    reg1 = apic_read(APIC_LVR);
    apic_printk(APIC_DEBUG, "Getting VERSION: %x\n", reg1);


    if (reg1 != reg0)
        return 0;


    reg1 = GET_APIC_VERSION(reg0);
    if (reg1 == 0x00 || reg1 == 0xff)
        return 0;
    reg1 = lapic_get_maxlvt();
    if (reg1 < 0x02 || reg1 == 0xff)
        return 0;


    reg0 = apic_read(APIC_ID);
    apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg0);
    apic_write(APIC_ID, reg0 ^ apic->apic_id_mask);
    reg1 = apic_read(APIC_ID);
    apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg1);
    apic_write(APIC_ID, reg0);
    if (reg1 != (reg0 ^ apic->apic_id_mask))
        return 0;


    reg0 = apic_read(APIC_LVT0);
    apic_printk(APIC_DEBUG, "Getting LVT0: %x\n", reg0);
    reg1 = apic_read(APIC_LVT1);
    apic_printk(APIC_DEBUG, "Getting LVT1: %x\n", reg1);

    return 1;
}
Exemplo n.º 6
0
static int __init enable_apic(void)
{
	uint msr_low, msr_high;
	uint val;

	/* enable local APIC via MSR. Forgetting this is a fun way to
	 * lock the box. But we have to hope this is allowed if the APIC
	 * has already been enabled.
	 *
	 * IA32 V3, 7.4.2 */
	rdmsr(MSR_IA32_APICBASE, msr_low, msr_high);
	if ((msr_low & (1 << 11)) == 0)
		wrmsr(MSR_IA32_APICBASE, msr_low | (1<<11), msr_high);

	/* even if the apic is up we must check for a good APIC */

	/* IA32 V3, 7.4.15 */
	val = apic_read(APIC_LVR);
	if (!APIC_INTEGRATED(GET_APIC_VERSION(val)))
		goto not_local_apic;

	/* LVT0,LVT1,LVTT,LVTPC */
	if (GET_APIC_MAXLVT(apic_read(APIC_LVR)) < 4)
		goto not_local_apic;

	/* IA32 V3, 7.4.14.1 */
	val = apic_read(APIC_SPIV);
	if (!(val & APIC_SPIV_APIC_ENABLED))
		apic_write(APIC_SPIV, val | APIC_SPIV_APIC_ENABLED);

	return !!(val & APIC_SPIV_APIC_ENABLED);

not_local_apic:
	/* disable the apic only if it was disabled */
	if ((msr_low & (1 << 11)) == 0)
		wrmsr(MSR_IA32_APICBASE, msr_low & ~(1<<11), msr_high);

	printk(KERN_ERR "oprofile: no suitable local APIC. Falling back to RTC mode.\n");
	return -ENODEV;
}
Exemplo n.º 7
0
static void __setup_APIC_LVTT(unsigned int clocks)
{
    unsigned int lvtt_value, tmp_value, ver;

    ver = GET_APIC_VERSION(apic_read(APIC_LVR));
    /* NB. Xen uses local APIC timer in one-shot mode. */
    lvtt_value = /*APIC_TIMER_MODE_PERIODIC |*/ LOCAL_TIMER_VECTOR;
    if (!APIC_INTEGRATED(ver))
        lvtt_value |= SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV);

    if ( tdt_enabled )
    {
        lvtt_value &= (~APIC_TIMER_MODE_MASK);
        lvtt_value |= APIC_TIMER_MODE_TSC_DEADLINE;
    }

    apic_write_around(APIC_LVTT, lvtt_value);

    tmp_value = apic_read(APIC_TDCR);
    apic_write_around(APIC_TDCR, (tmp_value | APIC_TDR_DIV_1));

    apic_write_around(APIC_TMICT, clocks/APIC_DIVISOR);
}
Exemplo n.º 8
0
static void __setup_APIC_LVTT(unsigned int clocks)
{
	unsigned int lvtt_value, tmp_value, ver;
	int cpu = smp_processor_id();

	ver = GET_APIC_VERSION(apic_read(APIC_LVR));
	lvtt_value = APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR;

	if (cpu_isset(cpu, timer_interrupt_broadcast_ipi_mask))
		lvtt_value |= APIC_LVT_MASKED;

	apic_write(APIC_LVTT, lvtt_value);

	/*
	 * Divide PICLK by 16
	 */
	tmp_value = apic_read(APIC_TDCR);
	apic_write(APIC_TDCR, (tmp_value
				& ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE))
				| APIC_TDR_DIV_16);

	apic_write(APIC_TMICT, clocks/APIC_DIVISOR);
}
Exemplo n.º 9
0
/*
 * For high res timers we want a single shot timer.
 * This means, for profiling, that we must load it each
 * interrupt, but it works best for timers as a one shot and
 * it is little overhead for the profiling which, we hope is
 * not done that often, nor on production machines.
 */
void __setup_APIC_LVTT(unsigned int clocks)
{
	unsigned int lvtt_value, tmp_value, ver;

	ver = GET_APIC_VERSION(apic_read(APIC_LVR));
	lvtt_value = 
#ifndef CONFIG_HIGH_RES_TIMERS
		APIC_LVT_TIMER_PERIODIC | 
#endif
		LOCAL_TIMER_VECTOR;
	if (!APIC_INTEGRATED(ver))
		lvtt_value |= SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV);
	apic_write_around(APIC_LVTT, lvtt_value);

	/*
	 * Divide PICLK by 16
	 */
	tmp_value = apic_read(APIC_TDCR);
	apic_write_around(APIC_TDCR, (tmp_value
				& ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE))
				| APIC_TDR_DIV_16);

	apic_write_around(APIC_TMICT, clocks/APIC_DIVISOR);
}
Exemplo n.º 10
0
/*
 * An initial setup of the virtual wire mode.
 */
void __init init_bsp_APIC(void)
{
	unsigned int value, ver;

	/*
	 * Don't do the setup now if we have a SMP BIOS as the
	 * through-I/O-APIC virtual wire mode might be active.
	 */
	if (smp_found_config || !cpu_has_apic)
		return;

	value = apic_read(APIC_LVR);
	ver = GET_APIC_VERSION(value);

	/*
	 * Do not trust the local APIC being empty at bootup.
	 */
	clear_local_APIC();

	/*
	 * Enable APIC.
	 */
	value = apic_read(APIC_SPIV);
	value &= ~APIC_VECTOR_MASK;
	value |= APIC_SPIV_APIC_ENABLED;
	value |= APIC_SPIV_FOCUS_DISABLED;
	value |= SPURIOUS_APIC_VECTOR;
	apic_write_around(APIC_SPIV, value);

	/*
	 * Set up the virtual wire mode.
	 */
	apic_write_around(APIC_LVT0, APIC_DM_EXTINT);
	value = APIC_DM_NMI;
	apic_write_around(APIC_LVT1, value);
}
Exemplo n.º 11
0
void __init setup_local_APIC (void)
{
	unsigned long oldvalue, value, ver, maxlvt;

	/* Pound the ESR really hard over the head with a big hammer - mbligh */
	if (esr_disable) {
		apic_write(APIC_ESR, 0);
		apic_write(APIC_ESR, 0);
		apic_write(APIC_ESR, 0);
		apic_write(APIC_ESR, 0);
	}

	value = apic_read(APIC_LVR);
	ver = GET_APIC_VERSION(value);

	if ((SPURIOUS_APIC_VECTOR & 0x0f) != 0x0f)
		__error_in_apic_c();

	/*
	 * Double-check whether this APIC is really registered.
	 */
	if (!apic_id_registered())
		BUG();

	/*
	 * Intel recommends to set DFR, LDR and TPR before enabling
	 * an APIC.  See e.g. "AP-388 82489DX User's Manual" (Intel
	 * document number 292116).  So here it goes...
	 */
	init_apic_ldr();

	/*
	 * Set Task Priority to 'accept all'. We never change this
	 * later on.
	 */
	value = apic_read(APIC_TASKPRI);
	value &= ~APIC_TPRI_MASK;
	apic_write_around(APIC_TASKPRI, value);

	/*
	 * Now that we are all set up, enable the APIC
	 */
	value = apic_read(APIC_SPIV);
	value &= ~APIC_VECTOR_MASK;
	/*
	 * Enable APIC
	 */
	value |= APIC_SPIV_APIC_ENABLED;

	/*
	 * Some unknown Intel IO/APIC (or APIC) errata is biting us with
	 * certain networking cards. If high frequency interrupts are
	 * happening on a particular IOAPIC pin, plus the IOAPIC routing
	 * entry is masked/unmasked at a high rate as well then sooner or
	 * later IOAPIC line gets 'stuck', no more interrupts are received
	 * from the device. If focus CPU is disabled then the hang goes
	 * away, oh well :-(
	 *
	 * [ This bug can be reproduced easily with a level-triggered
	 *   PCI Ne2000 networking cards and PII/PIII processors, dual
	 *   BX chipset. ]
	 */
	/*
	 * Actually disabling the focus CPU check just makes the hang less
	 * frequent as it makes the interrupt distributon model be more
	 * like LRU than MRU (the short-term load is more even across CPUs).
	 * See also the comment in end_level_ioapic_irq().  --macro
	 */
#if 1
	/* Enable focus processor (bit==0) */
	value &= ~APIC_SPIV_FOCUS_DISABLED;
#else
	/* Disable focus processor (bit==1) */
	value |= APIC_SPIV_FOCUS_DISABLED;
#endif
	/*
	 * Set spurious IRQ vector
	 */
	value |= SPURIOUS_APIC_VECTOR;
	apic_write_around(APIC_SPIV, value);

	/*
	 * Set up LVT0, LVT1:
	 *
	 * set up through-local-APIC on the BP's LINT0. This is not
	 * strictly necessery in pure symmetric-IO mode, but sometimes
	 * we delegate interrupts to the 8259A.
	 */
	/*
	 * TODO: set up through-local-APIC from through-I/O-APIC? --macro
	 */
	value = apic_read(APIC_LVT0) & APIC_LVT_MASKED;
	if (!smp_processor_id() && (pic_mode || !value)) {
		value = APIC_DM_EXTINT;
		apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n",
				smp_processor_id());
	} else {
		value = APIC_DM_EXTINT | APIC_LVT_MASKED;
		apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n",
				smp_processor_id());
	}
	apic_write_around(APIC_LVT0, value);

	/*
	 * only the BP should see the LINT1 NMI signal, obviously.
	 */
	if (!smp_processor_id())
		value = APIC_DM_NMI;
	else
		value = APIC_DM_NMI | APIC_LVT_MASKED;
	if (!APIC_INTEGRATED(ver))		/* 82489DX */
		value |= APIC_LVT_LEVEL_TRIGGER;
	apic_write_around(APIC_LVT1, value);

	if (APIC_INTEGRATED(ver) && !esr_disable) {		/* !82489DX */
		maxlvt = get_maxlvt();
		if (maxlvt > 3)		/* Due to the Pentium erratum 3AP. */
			apic_write(APIC_ESR, 0);
		oldvalue = apic_read(APIC_ESR);

		value = ERROR_APIC_VECTOR;      // enables sending errors
		apic_write_around(APIC_LVTERR, value);
		/*
		 * spec says clear errors after enabling vector.
		 */
		if (maxlvt > 3)
			apic_write(APIC_ESR, 0);
		value = apic_read(APIC_ESR);
		if (value != oldvalue)
			apic_printk(APIC_VERBOSE, "ESR value before enabling "
				"vector: 0x%08lx  after: 0x%08lx\n",
				oldvalue, value);
	} else {
		if (esr_disable)	
			/* 
			 * Something untraceble is creating bad interrupts on 
			 * secondary quads ... for the moment, just leave the
			 * ESR disabled - we can't do anything useful with the
			 * errors anyway - mbligh
			 */
			printk("Leaving ESR disabled.\n");
		else 
			printk("No ESR for 82489DX.\n");
	}

	if (nmi_watchdog == NMI_LOCAL_APIC)
		setup_apic_nmi_watchdog();
	apic_pm_activate();
}
Exemplo n.º 12
0
void __devinit setup_local_APIC(void)
{
    unsigned long oldvalue, value, ver, maxlvt;
    int i, j;

    /* Pound the ESR really hard over the head with a big hammer - mbligh */
    if (esr_disable) {
        apic_write(APIC_ESR, 0);
        apic_write(APIC_ESR, 0);
        apic_write(APIC_ESR, 0);
        apic_write(APIC_ESR, 0);
    }

    value = apic_read(APIC_LVR);
    ver = GET_APIC_VERSION(value);

    BUILD_BUG_ON((SPURIOUS_APIC_VECTOR & 0x0f) != 0x0f);

    /*
     * Double-check whether this APIC is really registered.
     */
    if (!apic_id_registered())
        BUG();

    /*
     * Intel recommends to set DFR, LDR and TPR before enabling
     * an APIC.  See e.g. "AP-388 82489DX User's Manual" (Intel
     * document number 292116).  So here it goes...
     */
    init_apic_ldr();

    /*
     * Set Task Priority to reject any interrupts below FIRST_DYNAMIC_VECTOR.
     */
    apic_write_around(APIC_TASKPRI, (FIRST_DYNAMIC_VECTOR & 0xF0) - 0x10);

    /*
     * After a crash, we no longer service the interrupts and a pending
     * interrupt from previous kernel might still have ISR bit set.
     *
     * Most probably by now CPU has serviced that pending interrupt and
     * it might not have done the ack_APIC_irq() because it thought,
     * interrupt came from i8259 as ExtInt. LAPIC did not get EOI so it
     * does not clear the ISR bit and cpu thinks it has already serivced
     * the interrupt. Hence a vector might get locked. It was noticed
     * for timer irq (vector 0x31). Issue an extra EOI to clear ISR.
     */
    for (i = APIC_ISR_NR - 1; i >= 0; i--) {
        value = apic_read(APIC_ISR + i*0x10);
        for (j = 31; j >= 0; j--) {
            if (value & (1<<j))
                ack_APIC_irq();
        }
    }

    /*
     * Now that we are all set up, enable the APIC
     */
    value = apic_read(APIC_SPIV);
    value &= ~APIC_VECTOR_MASK;
    /*
     * Enable APIC
     */
    value |= APIC_SPIV_APIC_ENABLED;

    /*
     * Some unknown Intel IO/APIC (or APIC) errata is biting us with
     * certain networking cards. If high frequency interrupts are
     * happening on a particular IOAPIC pin, plus the IOAPIC routing
     * entry is masked/unmasked at a high rate as well then sooner or
     * later IOAPIC line gets 'stuck', no more interrupts are received
     * from the device. If focus CPU is disabled then the hang goes
     * away, oh well :-(
     *
     * [ This bug can be reproduced easily with a level-triggered
     *   PCI Ne2000 networking cards and PII/PIII processors, dual
     *   BX chipset. ]
     */
    /*
     * Actually disabling the focus CPU check just makes the hang less
     * frequent as it makes the interrupt distributon model be more
     * like LRU than MRU (the short-term load is more even across CPUs).
     * See also the comment in end_level_ioapic_irq().  --macro
     */
#if 1
    /* Enable focus processor (bit==0) */
    value &= ~APIC_SPIV_FOCUS_DISABLED;
#else
    /* Disable focus processor (bit==1) */
    value |= APIC_SPIV_FOCUS_DISABLED;
#endif
    /*
     * Set spurious IRQ vector
     */
    value |= SPURIOUS_APIC_VECTOR;

    /*
     * Enable directed EOI
     */
    if ( directed_eoi_enabled )
    {
        value |= APIC_SPIV_DIRECTED_EOI;
        apic_printk(APIC_VERBOSE, "Suppress EOI broadcast on CPU#%d\n",
                    smp_processor_id());
    }

    apic_write_around(APIC_SPIV, value);

    /*
     * Set up LVT0, LVT1:
     *
     * set up through-local-APIC on the BP's LINT0. This is not
     * strictly necessery in pure symmetric-IO mode, but sometimes
     * we delegate interrupts to the 8259A.
     */
    /*
     * TODO: set up through-local-APIC from through-I/O-APIC? --macro
     */
    value = apic_read(APIC_LVT0) & APIC_LVT_MASKED;
    if (!smp_processor_id() && (pic_mode || !value)) {
        value = APIC_DM_EXTINT;
        apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n",
                    smp_processor_id());
    } else {
        value = APIC_DM_EXTINT | APIC_LVT_MASKED;
        apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n",
                    smp_processor_id());
    }
    apic_write_around(APIC_LVT0, value);

    /*
     * only the BP should see the LINT1 NMI signal, obviously.
     */
    if (!smp_processor_id())
        value = APIC_DM_NMI;
    else
        value = APIC_DM_NMI | APIC_LVT_MASKED;
    if (!APIC_INTEGRATED(ver))      /* 82489DX */
        value |= APIC_LVT_LEVEL_TRIGGER;
    apic_write_around(APIC_LVT1, value);

    if (APIC_INTEGRATED(ver) && !esr_disable) {        /* !82489DX */
        maxlvt = get_maxlvt();
        if (maxlvt > 3)     /* Due to the Pentium erratum 3AP. */
            apic_write(APIC_ESR, 0);
        oldvalue = apic_read(APIC_ESR);

        value = ERROR_APIC_VECTOR;      // enables sending errors
        apic_write_around(APIC_LVTERR, value);
        /*
         * spec says clear errors after enabling vector.
         */
        if (maxlvt > 3)
            apic_write(APIC_ESR, 0);
        value = apic_read(APIC_ESR);
        if (value != oldvalue)
            apic_printk(APIC_VERBOSE, "ESR value before enabling "
                        "vector: %#lx  after: %#lx\n",
                        oldvalue, value);
    } else {
        if (esr_disable)    
            /* 
             * Something untraceble is creating bad interrupts on 
             * secondary quads ... for the moment, just leave the
             * ESR disabled - we can't do anything useful with the
             * errors anyway - mbligh
             */
            printk("Leaving ESR disabled.\n");
        else
            printk("No ESR for 82489DX.\n");
    }

    if (nmi_watchdog == NMI_LOCAL_APIC)
        setup_apic_nmi_watchdog();
    apic_pm_activate();
}
Exemplo n.º 13
0
/*
 * This is to verify that we're looking at a real local APIC.
 * Check these against your board if the CPUs aren't getting
 * started for no apparent reason.
 */
int __init verify_local_APIC(void)
{
    unsigned int reg0, reg1;

    /*
     * The version register is read-only in a real APIC.
     */
    reg0 = apic_read(APIC_LVR);
    apic_printk(APIC_DEBUG, "Getting VERSION: %x\n", reg0);

    /* We don't try writing LVR in x2APIC mode since that incurs #GP. */
    if ( !x2apic_enabled )
        apic_write(APIC_LVR, reg0 ^ APIC_LVR_MASK);
    reg1 = apic_read(APIC_LVR);
    apic_printk(APIC_DEBUG, "Getting VERSION: %x\n", reg1);

    /*
     * The two version reads above should print the same
     * numbers.  If the second one is different, then we
     * poke at a non-APIC.
     */
    if (reg1 != reg0)
        return 0;

    /*
     * Check if the version looks reasonably.
     */
    reg1 = GET_APIC_VERSION(reg0);
    if (reg1 == 0x00 || reg1 == 0xff)
        return 0;
    reg1 = get_maxlvt();
    if (reg1 < 0x02 || reg1 == 0xff)
        return 0;

    /*
     * Detecting directed EOI on BSP:
     * If having directed EOI support in lapic, force to use ioapic_ack_old,
     * and enable the directed EOI for intr handling.
     */
    if ( reg0 & APIC_LVR_DIRECTED_EOI )
    {
        if ( ioapic_ack_new == 1 && ioapic_ack_forced == 1 )
            printk("Not enabling directed EOI because ioapic_ack_new has been "
                   "forced on the command line\n");
        else
        {
            ioapic_ack_new = 0;
            directed_eoi_enabled = 1;
            printk("Enabled directed EOI with ioapic_ack_old on!\n");
        }
    }

    /*
     * The ID register is read/write in a real APIC.
     */
    reg0 = apic_read(APIC_ID);
    apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg0);

    /*
     * The next two are just to see if we have sane values.
     * They're only really relevant if we're in Virtual Wire
     * compatibility mode, but most boxes are anymore.
     */
    reg0 = apic_read(APIC_LVT0);
    apic_printk(APIC_DEBUG, "Getting LVT0: %x\n", reg0);
    reg1 = apic_read(APIC_LVT1);
    apic_printk(APIC_DEBUG, "Getting LVT1: %x\n", reg1);

    return 1;
}
Exemplo n.º 14
0
void clear_local_APIC(void)
{
    int maxlvt;
    unsigned long v;

    maxlvt = get_maxlvt();

    /* Work around AMD Erratum 411. This is a nice thing to do anyway. */
    apic_write_around(APIC_TMICT, 0);

    /*
     * Masking an LVT entry on a P6 can trigger a local APIC error
     * if the vector is zero. Mask LVTERR first to prevent this.
     */
    if (maxlvt >= 3) {
        v = ERROR_APIC_VECTOR; /* any non-zero vector will do */
        apic_write_around(APIC_LVTERR, v | APIC_LVT_MASKED);
    }
    /*
     * Careful: we have to set masks only first to deassert
     * any level-triggered sources.
     */
    v = apic_read(APIC_LVTT);
    apic_write_around(APIC_LVTT, v | APIC_LVT_MASKED);
    v = apic_read(APIC_LVT0);
    apic_write_around(APIC_LVT0, v | APIC_LVT_MASKED);
    v = apic_read(APIC_LVT1);
    apic_write_around(APIC_LVT1, v | APIC_LVT_MASKED);
    if (maxlvt >= 4) {
        v = apic_read(APIC_LVTPC);
        apic_write_around(APIC_LVTPC, v | APIC_LVT_MASKED);
    }

/* lets not touch this if we didn't frob it */
#ifdef CONFIG_X86_MCE_THERMAL
    if (maxlvt >= 5) {
        v = apic_read(APIC_LVTTHMR);
        apic_write_around(APIC_LVTTHMR, v | APIC_LVT_MASKED);
    }
#endif

    if (maxlvt >= 6) {
        v = apic_read(APIC_CMCI);
        apic_write_around(APIC_CMCI, v | APIC_LVT_MASKED);
    }
    /*
     * Clean APIC state for other OSs:
     */
    apic_write_around(APIC_LVTT, APIC_LVT_MASKED);
    apic_write_around(APIC_LVT0, APIC_LVT_MASKED);
    apic_write_around(APIC_LVT1, APIC_LVT_MASKED);
    if (maxlvt >= 3)
        apic_write_around(APIC_LVTERR, APIC_LVT_MASKED);
    if (maxlvt >= 4)
        apic_write_around(APIC_LVTPC, APIC_LVT_MASKED);

#ifdef CONFIG_X86_MCE_THERMAL
    if (maxlvt >= 5)
        apic_write_around(APIC_LVTTHMR, APIC_LVT_MASKED);
#endif
    if (maxlvt >= 6)
        apic_write_around(APIC_CMCI, APIC_LVT_MASKED);

    v = GET_APIC_VERSION(apic_read(APIC_LVR));
    if (APIC_INTEGRATED(v)) {  /* !82489DX */
        if (maxlvt > 3)        /* Due to Pentium errata 3AP and 11AP. */
            apic_write(APIC_ESR, 0);
        apic_read(APIC_ESR);
    }
}
Exemplo n.º 15
0
/*
 * Get the LAPIC version
 */
static inline int lapic_get_version(void)
{
	return GET_APIC_VERSION(apic_read(APIC_LVR));
}
Exemplo n.º 16
0
/**
 * Prints various local APIC registers of interest to the console.
 */
void
lapic_dump(void)
{
	char buf[128];

	printk(KERN_DEBUG "LOCAL APIC DUMP (LOGICAL CPU #%d):\n", this_cpu);

	/*
 	 * Lead off with the important stuff...
 	 */
	printk(KERN_DEBUG
		"  ID:  0x%08x (id=%d)\n",
		apic_read(APIC_ID),
		GET_APIC_ID(apic_read(APIC_ID))
	);
	printk(KERN_DEBUG
		"  VER: 0x%08x (version=0x%x, max_lvt=%d)\n",
		apic_read(APIC_LVR),
		GET_APIC_VERSION(apic_read(APIC_LVR)),
		GET_APIC_MAXLVT(apic_read(APIC_LVR))
	);
	printk(KERN_DEBUG
		"  ESR: 0x%08x (Error Status Reg, non-zero is bad)\n",
		apic_read(APIC_ESR)
	);
	printk(KERN_DEBUG
		"  SVR: 0x%08x (Spurious vector=%d, %s)\n",
		apic_read(APIC_SPIV),
		apic_read(APIC_SPIV) & APIC_VECTOR_MASK,
		(apic_read(APIC_SPIV) & APIC_SPIV_APIC_ENABLED)
			? "APIC IS ENABLED"
			: "APIC IS DISABLED"
	);

	/*
 	 * Local Vector Table
 	 */
	printk(KERN_DEBUG "  Local Vector Table Entries:\n");
	printk(KERN_DEBUG "      LVT[0] Timer:     0x%08x (%s)\n",
		apic_read(APIC_LVTT),
		lvt_stringify(apic_read(APIC_LVTT), buf)
	);
	printk(KERN_DEBUG "      LVT[1] Thermal:   0x%08x (%s)\n",
		apic_read(APIC_LVTTHMR),
		lvt_stringify(apic_read(APIC_LVTTHMR), buf)
	);
	printk(KERN_DEBUG "      LVT[2] Perf Cnt:  0x%08x (%s)\n",
		apic_read(APIC_LVTPC),
		lvt_stringify(apic_read(APIC_LVTPC), buf)
	);
	printk(KERN_DEBUG "      LVT[3] LINT0 Pin: 0x%08x (%s)\n",
		apic_read(APIC_LVT0),
		lvt_stringify(apic_read(APIC_LVT0), buf)
	);
	printk(KERN_DEBUG "      LVT[4] LINT1 Pin: 0x%08x (%s)\n",
		apic_read(APIC_LVT1),
		lvt_stringify(apic_read(APIC_LVT1), buf)
	);
	printk(KERN_DEBUG "      LVT[5] Error:     0x%08x (%s)\n",
		apic_read(APIC_LVTERR),
		lvt_stringify(apic_read(APIC_LVTERR), buf)
	);

	/*
 	 * APIC timer configuration registers
 	 */
	printk(KERN_DEBUG "  Local APIC Timer:\n");
	printk(KERN_DEBUG "      DCR (Divide Config Reg): 0x%08x\n",
		apic_read(APIC_TDCR)
	);
	printk(KERN_DEBUG "      ICT (Initial Count Reg): 0x%08x\n",
		apic_read(APIC_TMICT)
	);
	printk(KERN_DEBUG "      CCT (Current Count Reg): 0x%08x\n",
		apic_read(APIC_TMCCT)
	);

	/*
 	 * Logical APIC addressing mode registers
 	 */
	printk(KERN_DEBUG "  Logical Addressing Mode Information:\n");
	printk(KERN_DEBUG "      LDR (Logical Dest Reg):  0x%08x (id=%d)\n",
		apic_read(APIC_LDR),
		GET_APIC_LOGICAL_ID(apic_read(APIC_LDR))
	);
	printk(KERN_DEBUG "      DFR (Dest Format Reg):   0x%08x (%s)\n",
		apic_read(APIC_DFR),
		(apic_read(APIC_DFR) == APIC_DFR_FLAT) ? "FLAT" : "CLUSTER"
	);

	/*
 	 * Task/processor/arbitration priority registers
 	 */
	printk(KERN_DEBUG "  Task/Processor/Arbitration Priorities:\n");
	printk(KERN_DEBUG "      TPR (Task Priority Reg):        0x%08x\n",
		apic_read(APIC_TASKPRI)
	);
	printk(KERN_DEBUG "      PPR (Processor Priority Reg):   0x%08x\n",
		apic_read(APIC_PROCPRI)
	);
	printk(KERN_DEBUG "      APR (Arbitration Priority Reg): 0x%08x\n",
		apic_read(APIC_ARBPRI)
	);
}