use memory barriers instead of read memory barriers to determine the current TSC

=> more accurate caclculation of the timer frequency
+ minor cosmetic changes
This commit is contained in:
Stefan Lankes 2011-04-18 15:07:45 +02:00
parent 624afd187c
commit 47f37e3b00
2 changed files with 22 additions and 17 deletions

View file

@ -140,7 +140,7 @@ static inline void tlb_flush(void)
static inline uint32_t read_eflags(void)
{
uint32_t result;
asm volatile ("pushf; popl %%eax" : "=a"(result) :: "memory");
asm volatile ("pushf; pop %%eax" : "=a"(result));
return result;
}

View file

@ -56,6 +56,7 @@ static apic_mp_t* apic_mp = NULL;
static apic_config_table_t* apic_config = NULL;
static uint32_t lapic = 0;
static volatile ioapic_t* ioapic = NULL;
static uint32_t icr = 0;
static uint32_t ncores = 1;
static uint8_t irq_redirect[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF};
#if MAX_CORES > 1
@ -256,19 +257,28 @@ int smp_init(void)
static int lapic_reset(void)
{
uint32_t max_lvt = apic_lvt_entries();
uint32_t max_lvt;
if (!lapic)
return -ENXIO;
max_lvt = apic_lvt_entries();
lapic_write(APIC_SVR, 0x17F); // enable the apic and connect to the idt entry 127
lapic_write(APIC_TPR, 0x00); // allow all interrupts
lapic_write(APIC_LVT_T, 0x10000); // disable timer interrupt
if (icr) {
lapic_write(APIC_DCR, 0xB); // set it to 1 clock increments
lapic_write(APIC_LVT_T, 0x2007B); // connects the timer to 123 and enables it
lapic_write(APIC_ICR, icr);
} else
lapic_write(APIC_LVT_T, 0x10000); // disable timer interrupt
if (max_lvt >= 4)
lapic_write(APIC_LVT_TSR, 0x10000); // disable thermal sensor interrupt
lapic_write(APIC_LVT_TSR, 0x10000); // disable thermal sensor interrupt
if (max_lvt >= 5)
lapic_write(APIC_LVT_PMC, 0x10000); // disable performance counter interrupt
lapic_write(APIC_LVT_PMC, 0x10000); // disable performance counter interrupt
lapic_write(APIC_LINT0, 0x7C); // connect LINT0 to idt entry 124
lapic_write(APIC_LINT1, 0x7D); // connect LINT1 to idt entry 125
lapic_write(APIC_LVT_ER, 0x7E); // connect error to idt entry 126
lapic_write(APIC_ID, 0x00); // reset boot processor id
return 0;
}
@ -328,13 +338,10 @@ int apic_calibration(void)
HALT;
diff = 0xFFFFFFFFUL - lapic_read(APIC_CCR);
diff = diff / 3;
icr = diff / 3;
flags = irq_nested_disable();
lapic_reset();
lapic_write(APIC_DCR, 0xB); // set it to 1 clock increments
lapic_write(APIC_LVT_T, 0x2007B); // connects the timer to 123 and enables it
lapic_write(APIC_ICR, diff);
irq_nested_enable(flags);
// Now, MetalSVM is able to use the APIC => Therefore, we disable the PIC
@ -353,26 +360,23 @@ int apic_calibration(void)
lapic_write(APIC_ICR, 0xFFFFFFFFUL);
/* wait 3 time slices to determine a ICR */
rmb();
mb();
start = rdtsc();
do {
rmb();
mb();
end = rdtsc();
ticks = end > start ? end - start : start - end;
} while(ticks*TIMER_FREQ < 3*RC_REFCLOCKMHZ*1000000UL);
diff = 0xFFFFFFFFUL - lapic_read(APIC_CCR);
diff = diff / 3;
icr = diff / 3;
lapic_reset();
lapic_write(APIC_DCR, 0xB); // set it to 1 clock increments
lapic_write(APIC_LVT_T, 0x2007B); // connects the timer to 123 and enables it
lapic_write(APIC_ICR, diff);
irq_nested_enable(flags);
#endif
kprintf("APIC calibration determines an ICR of 0x%x\n", diff);
kprintf("APIC calibration determines an ICR of 0x%x\n", icr);
flags = irq_nested_disable();
#if MAX_CORES > 1
@ -568,6 +572,7 @@ int apic_init(void)
// set APIC error handler
irq_install_handler(126, apic_err_handler);
// initialize local apic
ret = lapic_reset();
if (!ret)
return ret;