Use plain C in timer_rdtsc for division instead of inline asssembly.
This also fixes a bug in rdtsc_currticks when the result did not fix in %eax Signed-off-by: Alexey Zaytsev <zaytsev.a@protei.ru>
This commit is contained in:
parent
4704abbc50
commit
8de54ef9aa
|
@ -14,54 +14,32 @@
|
||||||
#define rdtscll(val) \
|
#define rdtscll(val) \
|
||||||
__asm__ __volatile__ ("rdtsc" : "=A" (val))
|
__asm__ __volatile__ ("rdtsc" : "=A" (val))
|
||||||
|
|
||||||
static unsigned long long calibrate_tsc(void)
|
|
||||||
|
/* Measure how many clocks we get in one microsecond */
|
||||||
|
static inline uint64_t calibrate_tsc(void)
|
||||||
{
|
{
|
||||||
uint32_t startlow, starthigh;
|
|
||||||
uint32_t endlow, endhigh;
|
|
||||||
|
|
||||||
rdtsc(startlow,starthigh);
|
uint64_t rdtsc_start;
|
||||||
i386_timer2_udelay(USECS_IN_MSEC/2);
|
uint64_t rdtsc_end;
|
||||||
rdtsc(endlow,endhigh);
|
|
||||||
|
|
||||||
/* 64-bit subtract - gcc just messes up with long longs */
|
rdtscll(rdtsc_start);
|
||||||
/* XXX ORLY? Check it. */
|
i386_timer2_udelay(USECS_IN_MSEC);
|
||||||
__asm__("subl %2,%0\n\t"
|
rdtscll(rdtsc_end);
|
||||||
"sbbl %3,%1"
|
|
||||||
:"=a" (endlow), "=d" (endhigh)
|
return (rdtsc_end - rdtsc_start) / USECS_IN_MSEC;
|
||||||
:"g" (startlow), "g" (starthigh),
|
|
||||||
"0" (endlow), "1" (endhigh));
|
|
||||||
|
|
||||||
/* Error: ECPUTOOFAST */
|
|
||||||
if (endhigh)
|
|
||||||
goto bad_ctc;
|
|
||||||
|
|
||||||
endlow *= MSECS_IN_SEC*2;
|
|
||||||
return endlow;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The CTC wasn't reliable: we got a hit on the very first read,
|
|
||||||
* or the CPU was so fast/slow that the quotient wouldn't fit in
|
|
||||||
* 32 bits..
|
|
||||||
*/
|
|
||||||
bad_ctc:
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
static uint32_t clocks_per_second = 0;
|
|
||||||
|
|
||||||
|
static uint32_t clocks_per_usec = 0;
|
||||||
|
|
||||||
|
/* We measure time in microseconds. */
|
||||||
static tick_t rdtsc_currticks(void)
|
static tick_t rdtsc_currticks(void)
|
||||||
{
|
{
|
||||||
uint32_t clocks_high, clocks_low;
|
uint64_t clocks;
|
||||||
uint32_t currticks;
|
|
||||||
|
|
||||||
/* Read the Time Stamp Counter */
|
/* Read the Time Stamp Counter */
|
||||||
rdtsc(clocks_low, clocks_high);
|
rdtscll(clocks);
|
||||||
|
|
||||||
/* currticks = clocks / clocks_per_tick; */
|
return clocks / clocks_per_usec;
|
||||||
__asm__("divl %1"
|
|
||||||
:"=a" (currticks)
|
|
||||||
:"r" (clocks_per_second/USECS_IN_SEC), "0" (clocks_low), "d" (clocks_high));
|
|
||||||
|
|
||||||
return currticks;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rdtsc_ts_init(void)
|
static int rdtsc_ts_init(void)
|
||||||
|
@ -71,10 +49,10 @@ static int rdtsc_ts_init(void)
|
||||||
|
|
||||||
get_cpuinfo(&cpu_info);
|
get_cpuinfo(&cpu_info);
|
||||||
if (cpu_info.features & X86_FEATURE_TSC) {
|
if (cpu_info.features & X86_FEATURE_TSC) {
|
||||||
clocks_per_second = calibrate_tsc();
|
clocks_per_usec= calibrate_tsc();
|
||||||
if (clocks_per_second) {
|
if (clocks_per_usec) {
|
||||||
DBG("RDTSC ticksource installed. CPU running at %ld Mhz\n",
|
DBG("RDTSC ticksource installed. CPU running at %ld Mhz\n",
|
||||||
clocks_per_second/(1000*1000));
|
clocks_per_usec);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in New Issue