Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* calibrate.c: default delay calibration
0003  *
0004  * Excised from init/main.c
0005  *  Copyright (C) 1991, 1992  Linus Torvalds
0006  */
0007 
0008 #include <linux/jiffies.h>
0009 #include <linux/delay.h>
0010 #include <linux/init.h>
0011 #include <linux/timex.h>
0012 #include <linux/smp.h>
0013 #include <linux/percpu.h>
0014 
0015 unsigned long lpj_fine;
0016 unsigned long preset_lpj;
0017 static int __init lpj_setup(char *str)
0018 {
0019     preset_lpj = simple_strtoul(str,NULL,0);
0020     return 1;
0021 }
0022 
0023 __setup("lpj=", lpj_setup);
0024 
0025 #ifdef ARCH_HAS_READ_CURRENT_TIMER
0026 
0027 /* This routine uses the read_current_timer() routine and gets the
0028  * loops per jiffy directly, instead of guessing it using delay().
0029  * Also, this code tries to handle non-maskable asynchronous events
0030  * (like SMIs)
0031  */
0032 #define DELAY_CALIBRATION_TICKS         ((HZ < 100) ? 1 : (HZ/100))
0033 #define MAX_DIRECT_CALIBRATION_RETRIES      5
0034 
0035 static unsigned long calibrate_delay_direct(void)
0036 {
0037     unsigned long pre_start, start, post_start;
0038     unsigned long pre_end, end, post_end;
0039     unsigned long start_jiffies;
0040     unsigned long timer_rate_min, timer_rate_max;
0041     unsigned long good_timer_sum = 0;
0042     unsigned long good_timer_count = 0;
0043     unsigned long measured_times[MAX_DIRECT_CALIBRATION_RETRIES];
0044     int max = -1; /* index of measured_times with max/min values or not set */
0045     int min = -1;
0046     int i;
0047 
0048     if (read_current_timer(&pre_start) < 0 )
0049         return 0;
0050 
0051     /*
0052      * A simple loop like
0053      *  while ( jiffies < start_jiffies+1)
0054      *      start = read_current_timer();
0055      * will not do. As we don't really know whether jiffy switch
0056      * happened first or timer_value was read first. And some asynchronous
0057      * event can happen between these two events introducing errors in lpj.
0058      *
0059      * So, we do
0060      * 1. pre_start <- When we are sure that jiffy switch hasn't happened
0061      * 2. check jiffy switch
0062      * 3. start <- timer value before or after jiffy switch
0063      * 4. post_start <- When we are sure that jiffy switch has happened
0064      *
0065      * Note, we don't know anything about order of 2 and 3.
0066      * Now, by looking at post_start and pre_start difference, we can
0067      * check whether any asynchronous event happened or not
0068      */
0069 
0070     for (i = 0; i < MAX_DIRECT_CALIBRATION_RETRIES; i++) {
0071         pre_start = 0;
0072         read_current_timer(&start);
0073         start_jiffies = jiffies;
0074         while (time_before_eq(jiffies, start_jiffies + 1)) {
0075             pre_start = start;
0076             read_current_timer(&start);
0077         }
0078         read_current_timer(&post_start);
0079 
0080         pre_end = 0;
0081         end = post_start;
0082         while (time_before_eq(jiffies, start_jiffies + 1 +
0083                            DELAY_CALIBRATION_TICKS)) {
0084             pre_end = end;
0085             read_current_timer(&end);
0086         }
0087         read_current_timer(&post_end);
0088 
0089         timer_rate_max = (post_end - pre_start) /
0090                     DELAY_CALIBRATION_TICKS;
0091         timer_rate_min = (pre_end - post_start) /
0092                     DELAY_CALIBRATION_TICKS;
0093 
0094         /*
0095          * If the upper limit and lower limit of the timer_rate is
0096          * >= 12.5% apart, redo calibration.
0097          */
0098         if (start >= post_end)
0099             printk(KERN_NOTICE "calibrate_delay_direct() ignoring "
0100                     "timer_rate as we had a TSC wrap around"
0101                     " start=%lu >=post_end=%lu\n",
0102                 start, post_end);
0103         if (start < post_end && pre_start != 0 && pre_end != 0 &&
0104             (timer_rate_max - timer_rate_min) < (timer_rate_max >> 3)) {
0105             good_timer_count++;
0106             good_timer_sum += timer_rate_max;
0107             measured_times[i] = timer_rate_max;
0108             if (max < 0 || timer_rate_max > measured_times[max])
0109                 max = i;
0110             if (min < 0 || timer_rate_max < measured_times[min])
0111                 min = i;
0112         } else
0113             measured_times[i] = 0;
0114 
0115     }
0116 
0117     /*
0118      * Find the maximum & minimum - if they differ too much throw out the
0119      * one with the largest difference from the mean and try again...
0120      */
0121     while (good_timer_count > 1) {
0122         unsigned long estimate;
0123         unsigned long maxdiff;
0124 
0125         /* compute the estimate */
0126         estimate = (good_timer_sum/good_timer_count);
0127         maxdiff = estimate >> 3;
0128 
0129         /* if range is within 12% let's take it */
0130         if ((measured_times[max] - measured_times[min]) < maxdiff)
0131             return estimate;
0132 
0133         /* ok - drop the worse value and try again... */
0134         good_timer_sum = 0;
0135         good_timer_count = 0;
0136         if ((measured_times[max] - estimate) <
0137                 (estimate - measured_times[min])) {
0138             printk(KERN_NOTICE "calibrate_delay_direct() dropping "
0139                     "min bogoMips estimate %d = %lu\n",
0140                 min, measured_times[min]);
0141             measured_times[min] = 0;
0142             min = max;
0143         } else {
0144             printk(KERN_NOTICE "calibrate_delay_direct() dropping "
0145                     "max bogoMips estimate %d = %lu\n",
0146                 max, measured_times[max]);
0147             measured_times[max] = 0;
0148             max = min;
0149         }
0150 
0151         for (i = 0; i < MAX_DIRECT_CALIBRATION_RETRIES; i++) {
0152             if (measured_times[i] == 0)
0153                 continue;
0154             good_timer_count++;
0155             good_timer_sum += measured_times[i];
0156             if (measured_times[i] < measured_times[min])
0157                 min = i;
0158             if (measured_times[i] > measured_times[max])
0159                 max = i;
0160         }
0161 
0162     }
0163 
0164     printk(KERN_NOTICE "calibrate_delay_direct() failed to get a good "
0165            "estimate for loops_per_jiffy.\nProbably due to long platform "
0166         "interrupts. Consider using \"lpj=\" boot option.\n");
0167     return 0;
0168 }
0169 #else
0170 static unsigned long calibrate_delay_direct(void)
0171 {
0172     return 0;
0173 }
0174 #endif
0175 
0176 /*
0177  * This is the number of bits of precision for the loops_per_jiffy.  Each
0178  * time we refine our estimate after the first takes 1.5/HZ seconds, so try
0179  * to start with a good estimate.
0180  * For the boot cpu we can skip the delay calibration and assign it a value
0181  * calculated based on the timer frequency.
0182  * For the rest of the CPUs we cannot assume that the timer frequency is same as
0183  * the cpu frequency, hence do the calibration for those.
0184  */
0185 #define LPS_PREC 8
0186 
0187 static unsigned long calibrate_delay_converge(void)
0188 {
0189     /* First stage - slowly accelerate to find initial bounds */
0190     unsigned long lpj, lpj_base, ticks, loopadd, loopadd_base, chop_limit;
0191     int trials = 0, band = 0, trial_in_band = 0;
0192 
0193     lpj = (1<<12);
0194 
0195     /* wait for "start of" clock tick */
0196     ticks = jiffies;
0197     while (ticks == jiffies)
0198         ; /* nothing */
0199     /* Go .. */
0200     ticks = jiffies;
0201     do {
0202         if (++trial_in_band == (1<<band)) {
0203             ++band;
0204             trial_in_band = 0;
0205         }
0206         __delay(lpj * band);
0207         trials += band;
0208     } while (ticks == jiffies);
0209     /*
0210      * We overshot, so retreat to a clear underestimate. Then estimate
0211      * the largest likely undershoot. This defines our chop bounds.
0212      */
0213     trials -= band;
0214     loopadd_base = lpj * band;
0215     lpj_base = lpj * trials;
0216 
0217 recalibrate:
0218     lpj = lpj_base;
0219     loopadd = loopadd_base;
0220 
0221     /*
0222      * Do a binary approximation to get lpj set to
0223      * equal one clock (up to LPS_PREC bits)
0224      */
0225     chop_limit = lpj >> LPS_PREC;
0226     while (loopadd > chop_limit) {
0227         lpj += loopadd;
0228         ticks = jiffies;
0229         while (ticks == jiffies)
0230             ; /* nothing */
0231         ticks = jiffies;
0232         __delay(lpj);
0233         if (jiffies != ticks)   /* longer than 1 tick */
0234             lpj -= loopadd;
0235         loopadd >>= 1;
0236     }
0237     /*
0238      * If we incremented every single time possible, presume we've
0239      * massively underestimated initially, and retry with a higher
0240      * start, and larger range. (Only seen on x86_64, due to SMIs)
0241      */
0242     if (lpj + loopadd * 2 == lpj_base + loopadd_base * 2) {
0243         lpj_base = lpj;
0244         loopadd_base <<= 2;
0245         goto recalibrate;
0246     }
0247 
0248     return lpj;
0249 }
0250 
0251 static DEFINE_PER_CPU(unsigned long, cpu_loops_per_jiffy) = { 0 };
0252 
0253 /*
0254  * Check if cpu calibration delay is already known. For example,
0255  * some processors with multi-core sockets may have all cores
0256  * with the same calibration delay.
0257  *
0258  * Architectures should override this function if a faster calibration
0259  * method is available.
0260  */
0261 unsigned long __attribute__((weak)) calibrate_delay_is_known(void)
0262 {
0263     return 0;
0264 }
0265 
0266 /*
0267  * Indicate the cpu delay calibration is done. This can be used by
0268  * architectures to stop accepting delay timer registrations after this point.
0269  */
0270 
0271 void __attribute__((weak)) calibration_delay_done(void)
0272 {
0273 }
0274 
0275 void calibrate_delay(void)
0276 {
0277     unsigned long lpj;
0278     static bool printed;
0279     int this_cpu = smp_processor_id();
0280 
0281     if (per_cpu(cpu_loops_per_jiffy, this_cpu)) {
0282         lpj = per_cpu(cpu_loops_per_jiffy, this_cpu);
0283         if (!printed)
0284             pr_info("Calibrating delay loop (skipped) "
0285                 "already calibrated this CPU");
0286     } else if (preset_lpj) {
0287         lpj = preset_lpj;
0288         if (!printed)
0289             pr_info("Calibrating delay loop (skipped) "
0290                 "preset value.. ");
0291     } else if ((!printed) && lpj_fine) {
0292         lpj = lpj_fine;
0293         pr_info("Calibrating delay loop (skipped), "
0294             "value calculated using timer frequency.. ");
0295     } else if ((lpj = calibrate_delay_is_known())) {
0296         ;
0297     } else if ((lpj = calibrate_delay_direct()) != 0) {
0298         if (!printed)
0299             pr_info("Calibrating delay using timer "
0300                 "specific routine.. ");
0301     } else {
0302         if (!printed)
0303             pr_info("Calibrating delay loop... ");
0304         lpj = calibrate_delay_converge();
0305     }
0306     per_cpu(cpu_loops_per_jiffy, this_cpu) = lpj;
0307     if (!printed)
0308         pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n",
0309             lpj/(500000/HZ),
0310             (lpj/(5000/HZ)) % 100, lpj);
0311 
0312     loops_per_jiffy = lpj;
0313     printed = true;
0314 
0315     calibration_delay_done();
0316 }