* When cpufreq levels change, find out about the (new) max frequency. We * use this to update CPU accounting in case it got a lower estimate at boot. */
| 709 | * use this to update CPU accounting in case it got a lower estimate at boot. |
| 710 | */ |
| 711 | static void |
| 712 | tsc_levels_changed(void *arg, int unit) |
| 713 | { |
| 714 | device_t cf_dev; |
| 715 | struct cf_level *levels; |
| 716 | int count, error; |
| 717 | uint64_t max_freq; |
| 718 | |
| 719 | /* Only use values from the first CPU, assuming all are equal. */ |
| 720 | if (unit != 0) |
| 721 | return; |
| 722 | |
| 723 | /* Find the appropriate cpufreq device instance. */ |
| 724 | cf_dev = devclass_get_device(devclass_find("cpufreq"), unit); |
| 725 | if (cf_dev == NULL) { |
| 726 | printf("tsc_levels_changed() called but no cpufreq device?\n"); |
| 727 | return; |
| 728 | } |
| 729 | |
| 730 | /* Get settings from the device and find the max frequency. */ |
| 731 | count = 64; |
| 732 | levels = malloc(count * sizeof(*levels), M_TEMP, M_NOWAIT); |
| 733 | if (levels == NULL) |
| 734 | return; |
| 735 | error = CPUFREQ_LEVELS(cf_dev, levels, &count); |
| 736 | if (error == 0 && count != 0) { |
| 737 | max_freq = (uint64_t)levels[0].total_set.freq * 1000000; |
| 738 | set_cputicker(rdtsc, max_freq, 1); |
| 739 | } else |
| 740 | printf("tsc_levels_changed: no max freq found\n"); |
| 741 | free(levels, M_TEMP); |
| 742 | } |
| 743 | |
| 744 | /* |
| 745 | * If the TSC timecounter is in use, veto the pending change. It may be |
nothing calls this directly
no test coverage detected