KVM: SVM: Get rid of x86_intercept_map::valid
[pandora-kernel.git] / init / calibrate.c
index f9000df..76ac919 100644 (file)
@@ -122,7 +122,7 @@ static unsigned long __cpuinit calibrate_delay_direct(void) {return 0;}
 static unsigned long __cpuinit calibrate_delay_converge(void)
 {
        /* First stage - slowly accelerate to find initial bounds */
-       unsigned long lpj, ticks, loopadd, chop_limit;
+       unsigned long lpj, lpj_base, ticks, loopadd, loopadd_base, chop_limit;
        int trials = 0, band = 0, trial_in_band = 0;
 
        lpj = (1<<12);
@@ -146,14 +146,18 @@ static unsigned long __cpuinit calibrate_delay_converge(void)
         * the largest likely undershoot. This defines our chop bounds.
         */
        trials -= band;
-       loopadd = lpj * band;
-       lpj *= trials;
-       chop_limit = lpj >> (LPS_PREC + 1);
+       loopadd_base = lpj * band;
+       lpj_base = lpj * trials;
+
+recalibrate:
+       lpj = lpj_base;
+       loopadd = loopadd_base;
 
        /*
         * Do a binary approximation to get lpj set to
         * equal one clock (up to LPS_PREC bits)
         */
+       chop_limit = lpj >> LPS_PREC;
        while (loopadd > chop_limit) {
                lpj += loopadd;
                ticks = jiffies;
@@ -165,6 +169,16 @@ static unsigned long __cpuinit calibrate_delay_converge(void)
                        lpj -= loopadd;
                loopadd >>= 1;
        }
+       /*
+        * If we incremented every single time possible, presume we've
+        * massively underestimated initially, and retry with a higher
+        * start, and larger range. (Only seen on x86_64, due to SMIs)
+        */
+       if (lpj + loopadd * 2 == lpj_base + loopadd_base * 2) {
+               lpj_base = lpj;
+               loopadd_base <<= 2;
+               goto recalibrate;
+       }
 
        return lpj;
 }