37,7 → 37,7 |
|
unsigned char use_tsc = 1; //Enable the TSC counter mode |
unsigned char use_cmos = 0; //Enable the RTC correction |
unsigned char use_apic = 0; //Enable the APIC |
unsigned char use_apic = 1; //Enable the APIC |
|
//Max single delta_clk_per_msec increment = clk_per_msec / MAX_DIV_INK; |
#define MAX_DIV_INK 30000 |
428,36 → 428,6 |
} |
} |
|
void connect_bsp_APIC(void) |
{ |
/* |
* Do not trust the local APIC being empty at bootup. |
*/ |
clear_local_APIC(); |
/* |
* PIC mode, enable APIC mode in the IMCR, i.e. |
* connect BSP's local APIC to INT and NMI lines. |
*/ |
outp(0x22, 0x70); |
outp(0x23, 0x01); |
|
} |
|
void disconnect_bsp_APIC(void) |
{ |
|
/* |
* Put the board back into PIC mode (has an effect |
* only on certain older boards). Note that APIC |
* interrupts, including IPIs, won't work beyond |
* this point! The only exception are INIT IPIs. |
*/ |
|
outp(0x22, 0x70); |
outp(0x23, 0x00); |
|
} |
|
void disable_local_APIC(void) |
{ |
unsigned long value; |
481,7 → 451,7 |
|
void setup_local_APIC (void) |
{ |
unsigned long value, ver; |
unsigned long value; |
|
/* Pound the ESR really hard over the head with a big hammer - mbligh */ |
|
490,77 → 460,17 |
apic_write(APIC_ESR, 0); |
apic_write(APIC_ESR, 0); |
|
value = apic_read(APIC_LVR); |
ver = GET_APIC_VERSION(value); |
value = APIC_SPIV_FOCUS_DISABLED | APIC_SPIV_APIC_ENABLED | SPURIOUS_APIC_VECTOR; |
apic_write_around(APIC_SPIV, value); |
|
/* |
* 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); |
value = APIC_DM_EXTINT | APIC_LVT_LEVEL_TRIGGER; |
apic_write_around(APIC_LVT0, 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; |
value = APIC_DM_NMI; |
apic_write_around(APIC_LVT1, value); |
|
/* |
* 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); |
apic_write(APIC_ESR, 0); |
|
/* |
* 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_DM_EXTINT; |
apic_write_around(APIC_LVT0, value); |
|
value = APIC_DM_NMI | APIC_LVT_MASKED; |
if (!APIC_INTEGRATED(ver)) /* 82489DX */ |
value |= APIC_LVT_LEVEL_TRIGGER; |
apic_write_around(APIC_LVT1, value); |
|
} |
|
void disable_APIC_timer(void) |
581,7 → 491,7 |
|
} |
|
#define LOCAL_TIMER_VECTOR 0x40 |
#define LOCAL_TIMER_VECTOR 0x66 |
|
void setup_APIC_LVTT(unsigned int clocks) |
{ |
668,19 → 578,15 |
if (use_apic) { |
unsigned long msr_low_orig, tmp; |
|
cli(); |
|
rdmsr(APIC_BASE_MSR, msr_low_orig, tmp); |
wrmsr(APIC_BASE_MSR, msr_low_orig|(1<<11), 0); |
|
connect_bsp_APIC(); |
clear_local_APIC(); |
|
ll_calibrate_apic(); |
|
setup_local_APIC(); |
|
sti(); |
|
ll_calibrate_apic(); |
|
} |
|
if (use_cmos) { |
711,7 → 617,7 |
|
} |
|
void ll_restore_CMOS() |
void ll_restore_adv() |
{ |
if (use_cmos) { |
cli(); |
723,4 → 629,21 |
|
sti(); |
} |
|
if (use_apic) { |
unsigned int msr_low_orig, tmp; |
|
cli(); |
|
disable_APIC_timer(); |
|
clear_local_APIC(); |
|
rdmsr(APIC_BASE_MSR, msr_low_orig, tmp); |
wrmsr(APIC_BASE_MSR, msr_low_orig&~(1<<11), 0); |
|
sti(); |
|
} |
|
} |