⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 apic.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 3 页
字号:
    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);    /*     * 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;    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();}static struct {    int active;    /* r/w apic fields */    unsigned int apic_id;    unsigned int apic_taskpri;    unsigned int apic_ldr;    unsigned int apic_dfr;    unsigned int apic_spiv;    unsigned int apic_lvtt;    unsigned int apic_lvtpc;    unsigned int apic_lvt0;    unsigned int apic_lvt1;    unsigned int apic_lvterr;    unsigned int apic_tmict;    unsigned int apic_tdcr;    unsigned int apic_thmr;} apic_pm_state;int lapic_suspend(void){    unsigned long flags;    if (!apic_pm_state.active)        return 0;    apic_pm_state.apic_id = apic_read(APIC_ID);    apic_pm_state.apic_taskpri = apic_read(APIC_TASKPRI);    apic_pm_state.apic_ldr = apic_read(APIC_LDR);    if ( !x2apic_enabled )        apic_pm_state.apic_dfr = apic_read(APIC_DFR);    apic_pm_state.apic_spiv = apic_read(APIC_SPIV);    apic_pm_state.apic_lvtt = apic_read(APIC_LVTT);    apic_pm_state.apic_lvtpc = apic_read(APIC_LVTPC);    apic_pm_state.apic_lvt0 = apic_read(APIC_LVT0);    apic_pm_state.apic_lvt1 = apic_read(APIC_LVT1);    apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR);    apic_pm_state.apic_tmict = apic_read(APIC_TMICT);    apic_pm_state.apic_tdcr = apic_read(APIC_TDCR);    apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR);        local_irq_save(flags);    disable_local_APIC();    local_irq_restore(flags);    return 0;}int lapic_resume(void){    unsigned int l, h;    unsigned long flags;    if (!apic_pm_state.active)        return 0;    local_irq_save(flags);    /*     * Make sure the APICBASE points to the right address     *     * FIXME! This will be wrong if we ever support suspend on     * SMP! We'll need to do this as part of the CPU restore!     */    if ( !x2apic_enabled )    {        rdmsr(MSR_IA32_APICBASE, l, h);        l &= ~MSR_IA32_APICBASE_BASE;        l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr;        wrmsr(MSR_IA32_APICBASE, l, h);    }    else        enable_x2apic();    apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED);    apic_write(APIC_ID, apic_pm_state.apic_id);    if ( !x2apic_enabled )        apic_write(APIC_DFR, apic_pm_state.apic_dfr);    apic_write(APIC_LDR, apic_pm_state.apic_ldr);    apic_write(APIC_TASKPRI, apic_pm_state.apic_taskpri);    apic_write(APIC_SPIV, apic_pm_state.apic_spiv);    apic_write(APIC_LVT0, apic_pm_state.apic_lvt0);    apic_write(APIC_LVT1, apic_pm_state.apic_lvt1);    apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr);    apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc);    apic_write(APIC_LVTT, apic_pm_state.apic_lvtt);    apic_write(APIC_TDCR, apic_pm_state.apic_tdcr);    apic_write(APIC_TMICT, apic_pm_state.apic_tmict);    apic_write(APIC_ESR, 0);    apic_read(APIC_ESR);    apic_write(APIC_LVTERR, apic_pm_state.apic_lvterr);    apic_write(APIC_ESR, 0);    apic_read(APIC_ESR);    local_irq_restore(flags);    return 0;}/* * If Linux enabled the LAPIC against the BIOS default * disable it down before re-entering the BIOS on shutdown. * Otherwise the BIOS may get confused and not power-off. * Additionally clear all LVT entries before disable_local_APIC * for the case where Linux didn't enable the LAPIC. */void lapic_shutdown(void){    unsigned long flags;    if (!cpu_has_apic)        return;    local_irq_save(flags);    clear_local_APIC();    if (enabled_via_apicbase)        disable_local_APIC();    local_irq_restore(flags);}static void apic_pm_activate(void){    apic_pm_state.active = 1;}/* * Detect and enable local APICs on non-SMP boards. * Original code written by Keir Fraser. */static void __init lapic_disable(char *str){    enable_local_apic = -1;    clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);}custom_param("nolapic", lapic_disable);static void __init lapic_enable(char *str){    enable_local_apic = 1;}custom_param("lapic", lapic_enable);static void __init apic_set_verbosity(char *str){    if (strcmp("debug", str) == 0)        apic_verbosity = APIC_DEBUG;    else if (strcmp("verbose", str) == 0)        apic_verbosity = APIC_VERBOSE;    else        printk(KERN_WARNING "APIC Verbosity level %s not recognised"               " use apic_verbosity=verbose or apic_verbosity=debug", str);}custom_param("apic_verbosity", apic_set_verbosity);static int __init detect_init_APIC (void){    u32 h, l, features;    /* Disabled by kernel option? */    if (enable_local_apic < 0)        return -1;    switch (boot_cpu_data.x86_vendor) {    case X86_VENDOR_AMD:        if ((boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model > 1) ||            (boot_cpu_data.x86 >= 15 && boot_cpu_data.x86 <= 17))            break;        goto no_apic;    case X86_VENDOR_INTEL:        if (boot_cpu_data.x86 == 6 || boot_cpu_data.x86 == 15 ||            (boot_cpu_data.x86 == 5 && cpu_has_apic))            break;        goto no_apic;    default:        goto no_apic;    }    if (!cpu_has_apic) {        /*         * Over-ride BIOS and try to enable the local         * APIC only if "lapic" specified.         */        if (enable_local_apic <= 0) {            printk("Local APIC disabled by BIOS -- "                   "you can enable it with \"lapic\"\n");            return -1;        }        /*         * Some BIOSes disable the local APIC in the         * APIC_BASE MSR. This can only be done in         * software for Intel P6 or later and AMD K7         * (Model > 1) or later.         */        rdmsr(MSR_IA32_APICBASE, l, h);        if (!(l & MSR_IA32_APICBASE_ENABLE)) {            printk("Local APIC disabled by BIOS -- reenabling.\n");            l &= ~MSR_IA32_APICBASE_BASE;            l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;            wrmsr(MSR_IA32_APICBASE, l, h);            enabled_via_apicbase = 1;        }    }    /*     * The APIC feature bit should now be enabled     * in `cpuid'     */    features = cpuid_edx(1);    if (!(features & (1 << X86_FEATURE_APIC))) {        printk("Could not enable APIC!\n");        return -1;    }    set_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);    mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;    /* The BIOS may have set up the APIC at some other address */    rdmsr(MSR_IA32_APICBASE, l, h);    if (l & MSR_IA32_APICBASE_ENABLE)        mp_lapic_addr = l & MSR_IA32_APICBASE_BASE;    if (nmi_watchdog != NMI_NONE)        nmi_watchdog = NMI_LOCAL_APIC;    printk("Found and enabled local APIC!\n");    apic_pm_activate();    return 0;no_apic:    printk("No local APIC present or hardware disabled\n");    return -1;}void enable_x2apic(void){    u32 lo, hi;    rdmsr(MSR_IA32_APICBASE, lo, hi);    if ( !(lo & MSR_IA32_APICBASE_EXTD) )    {        lo |= MSR_IA32_APICBASE_ENABLE | MSR_IA32_APICBASE_EXTD;        wrmsr(MSR_IA32_APICBASE, lo, 0);        printk("x2APIC mode enabled.\n");    }    else        printk("x2APIC mode enabled by BIOS.\n");    x2apic_enabled = 1;}void __init init_apic_mappings(void){    unsigned long apic_phys;    if ( x2apic_enabled )        goto __next;    /*     * If no local APIC can be found then set up a fake all     * zeroes page to simulate the local APIC and another     * one for the IO-APIC.     */    if (!smp_found_config && detect_init_APIC()) {        apic_phys = __pa(alloc_xenheap_page());        clear_page(__va(apic_phys));    } else        apic_phys = mp_lapic_addr;    set_fixmap_nocache(FIX_APIC_BASE, apic_phys);    apic_printk(APIC_VERBOSE, "mapped APIC to %08lx (%08lx)\n", APIC_BASE,                apic_phys);__next:    /*     * Fetch the APIC ID of the BSP in case we have a     * default configuration (or the MP table is broken).     */    if (boot_cpu_physical_apicid == -1U)        boot_cpu_physical_apicid = get_apic_id();#ifdef CONFIG_X86_IO_APIC    {        unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;        int i;        for (i = 0; i < nr_ioapics; i++) {            if (smp_found_config) {                ioapic_phys = mp_ioapics[i].mpc_apicaddr;                if (!ioapic_phys) {                    printk(KERN_ERR                           "WARNING: bogus zero IO-APIC "                           "address found in MPTABLE, "                           "disabling IO/APIC support!\n");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -