Chameleon

Chameleon Commit Details

Date:2012-05-08 13:54:11 (11 years 11 months ago)
Author:Cosmosis Jones
Commit:1944
Parents: 1943
Message:tsc fix for failed detection (discovered from kvm) http://forge.voodooprojects.org/p/chameleon/issues/246/
Changes:
M/trunk/i386/libsaio/cpu.c
M/trunk/i386/libsaio/cpu.h

File differences

trunk/i386/libsaio/cpu.c
2020
2121
2222
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
2393
2494
2595
......
281351
282352
283353
354
355
356
357
358
284359
285360
286361
#endif
/*
* timeRDTSC()
* This routine sets up PIT counter 2 to count down 1/20 of a second.
* It pauses until the value is latched in the counter
* and then reads the time stamp counter to return to the caller.
*/
uint64_t timeRDTSC(void)
{
intattempts = 0;
uint64_t latchTime;
uint64_tsaveTime,intermediate;
unsigned int timerValue, lastValue;
//boolean_tint_enabled;
/*
* Table of correction factors to account for
* - timer counter quantization errors, and
* - undercounts 0..5
*/
#define SAMPLE_CLKS_EXACT(((double) CLKNUM) / 20.0)
#define SAMPLE_CLKS_INT((int) CLKNUM / 20)
#define SAMPLE_NSECS(2000000000LL)
#define SAMPLE_MULTIPLIER(((double)SAMPLE_NSECS)*SAMPLE_CLKS_EXACT)
#define ROUND64(x)((uint64_t)((x) + 0.5))
uint64_tscale[6] = {
ROUND64(SAMPLE_MULTIPLIER/(double)(SAMPLE_CLKS_INT-0)),
ROUND64(SAMPLE_MULTIPLIER/(double)(SAMPLE_CLKS_INT-1)),
ROUND64(SAMPLE_MULTIPLIER/(double)(SAMPLE_CLKS_INT-2)),
ROUND64(SAMPLE_MULTIPLIER/(double)(SAMPLE_CLKS_INT-3)),
ROUND64(SAMPLE_MULTIPLIER/(double)(SAMPLE_CLKS_INT-4)),
ROUND64(SAMPLE_MULTIPLIER/(double)(SAMPLE_CLKS_INT-5))
};
restart:
if (attempts >= 9) // increase to up to 9 attempts.
// This will flash-reboot. TODO: Use tscPanic instead.
printf("Timestamp counter calibation failed with %d attempts\n", attempts);
attempts++;
enable_PIT2();// turn on PIT2
set_PIT2(0);// reset timer 2 to be zero
latchTime = rdtsc64();// get the time stamp to time
latchTime = get_PIT2(&timerValue) - latchTime; // time how long this takes
set_PIT2(SAMPLE_CLKS_INT);// set up the timer for (almost) 1/20th a second
saveTime = rdtsc64();// now time how long a 20th a second is...
get_PIT2(&lastValue);
get_PIT2(&lastValue);// read twice, first value may be unreliable
do {
intermediate = get_PIT2(&timerValue);
if (timerValue > lastValue) {
// Timer wrapped
set_PIT2(0);
disable_PIT2();
goto restart;
}
lastValue = timerValue;
} while (timerValue > 5);
printf("timerValue %d\n",timerValue);
printf("intermediate 0x%016llx\n",intermediate);
printf("saveTime 0x%016llx\n",saveTime);
intermediate -= saveTime;// raw count for about 1/20 second
intermediate *= scale[timerValue];// rescale measured time spent
intermediate /= SAMPLE_NSECS;// so its exactly 1/20 a second
intermediate += latchTime;// add on our save fudge
set_PIT2(0);// reset timer 2 to be zero
disable_PIT2();// turn off PIT 2
return intermediate;
}
/*
* DFE: Measures the TSC frequency in Hz (64-bit) using the ACPI PM timer
*/
static uint64_t measure_tsc_frequency(void)
}
tscFrequency = measure_tsc_frequency();
/* if usual method failed */
if ( tscFrequency < 1000 )
{
tscFrequency = timeRDTSC() * 20;
}
fsbFrequency = 0;
cpuFrequency = 0;
trunk/i386/libsaio/cpu.h
164164
165165
166166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
167233
return count;
}
inline static void
set_PIT2(int value)
{
/*
* First, tell the clock we are going to write 16 bits to the counter
* and enable one-shot mode (command 0xB8 to port 0x43)
* Then write the two bytes into the PIT2 clock register (port 0x42).
* Loop until the value is "realized" in the clock,
* this happens on the next tick.
*/
asm volatile(
" movb $0xB8,%%al \n\t"
" outb %%al,$0x43 \n\t"
" movb %%dl,%%al \n\t"
" outb %%al,$0x42 \n\t"
" movb %%dh,%%al \n\t"
" outb %%al,$0x42 \n"
"1: inb $0x42,%%al \n\t"
" inb $0x42,%%al \n\t"
" cmp %%al,%%dh \n\t"
" jne 1b"
: : "d"(value) : "%al");
}
inline static uint64_t
get_PIT2(unsigned int *value)
{
register uint64_t result;
/*
* This routine first latches the time (command 0x80 to port 0x43),
* then gets the time stamp so we know how long the read will take later.
* Read (from port 0x42) and return the current value of the timer.
*/
#ifdef __i386__
asm volatile(
" xorl %%ecx,%%ecx \n\t"
" movb $0x80,%%al \n\t"
" outb %%al,$0x43 \n\t"
" rdtsc \n\t"
" pushl %%eax \n\t"
" inb $0x42,%%al \n\t"
" movb %%al,%%cl \n\t"
" inb $0x42,%%al \n\t"
" movb %%al,%%ch \n\t"
" popl %%eax "
: "=A"(result), "=c"(*value));
#else /* __x86_64__ */
asm volatile(
" xorq %%rcx,%%rcx \n\t"
" movb $0x80,%%al \n\t"
" outb %%al,$0x43 \n\t"
" rdtsc \n\t"
" pushq %%rax \n\t"
" inb $0x42,%%al \n\t"
" movb %%al,%%cl \n\t"
" inb $0x42,%%al \n\t"
" movb %%al,%%ch \n\t"
" popq %%rax "
: "=A"(result), "=c"(*value));
#endif
return result;
}
#endif /* !__LIBSAIO_CPU_H */

Archive Download the corresponding diff file

Revision: 1944