The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/osfmk/i386/tsc.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2005-2007 Apple Inc. All rights reserved.
    3  *
    4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
    5  * 
    6  * This file contains Original Code and/or Modifications of Original Code
    7  * as defined in and that are subject to the Apple Public Source License
    8  * Version 2.0 (the 'License'). You may not use this file except in
    9  * compliance with the License. The rights granted to you under the License
   10  * may not be used to create, or enable the creation or redistribution of,
   11  * unlawful or unlicensed copies of an Apple operating system, or to
   12  * circumvent, violate, or enable the circumvention or violation of, any
   13  * terms of an Apple operating system software license agreement.
   14  * 
   15  * Please obtain a copy of the License at
   16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
   17  * 
   18  * The Original Code and all software distributed under the License are
   19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   23  * Please see the License for the specific language governing rights and
   24  * limitations under the License.
   25  * 
   26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
   27  */
   28 /*
   29  * @OSF_COPYRIGHT@
   30  */
   31 
   32 /*
   33  *      File:           i386/tsc.c
   34  *      Purpose:        Initializes the TSC and the various conversion
   35  *                      factors needed by other parts of the system.
   36  */
   37 
   38 #include <platforms.h>
   39 #include <mach_kdb.h>
   40 
   41 #include <mach/mach_types.h>
   42 
   43 #include <kern/cpu_data.h>
   44 #include <kern/cpu_number.h>
   45 #include <kern/clock.h>
   46 #include <kern/host_notify.h>
   47 #include <kern/macro_help.h>
   48 #include <kern/misc_protos.h>
   49 #include <kern/spl.h>
   50 #include <kern/assert.h>
   51 #include <mach/vm_prot.h>
   52 #include <vm/pmap.h>
   53 #include <vm/vm_kern.h>         /* for kernel_map */
   54 #include <architecture/i386/pio.h>
   55 #include <i386/machine_cpu.h>
   56 #include <i386/cpuid.h>
   57 #include <i386/mp.h>
   58 #include <i386/machine_routines.h>
   59 #include <i386/proc_reg.h>
   60 #include <i386/tsc.h>
   61 #include <i386/misc_protos.h>
   62 #include <pexpert/pexpert.h>
   63 #include <machine/limits.h>
   64 #include <machine/commpage.h>
   65 #include <sys/kdebug.h>
   66 #include <pexpert/device_tree.h>
   67 
   68 uint64_t        busFCvtt2n = 0;
   69 uint64_t        busFCvtn2t = 0;
   70 uint64_t        tscFreq = 0;
   71 uint64_t        tscFCvtt2n = 0;
   72 uint64_t        tscFCvtn2t = 0;
   73 uint64_t        tscGranularity = 0;
   74 uint64_t        bus2tsc = 0;
   75 uint64_t        busFreq = 0;
   76 uint32_t        flex_ratio = 0;
   77 uint32_t        flex_ratio_min = 0;
   78 uint32_t        flex_ratio_max = 0;
   79 
   80 
   81 #define bit(n)          (1ULL << (n))
   82 #define bitmask(h,l)    ((bit(h)|(bit(h)-1)) & ~(bit(l)-1))
   83 #define bitfield(x,h,l) (((x) & bitmask(h,l)) >> l)
   84 
   85 /* Decimal powers: */
   86 #define kilo (1000ULL)
   87 #define Mega (kilo * kilo)
   88 #define Giga (kilo * Mega)
   89 #define Tera (kilo * Giga)
   90 #define Peta (kilo * Tera)
   91 
   92 #define CPU_FAMILY_PENTIUM_M    (0x6)
   93 
   94 static const char       FSB_Frequency_prop[] = "FSBFrequency";
   95 /*
   96  * This routine extracts the bus frequency in Hz from the device tree.
   97  */
   98 static uint64_t
   99 EFI_FSB_frequency(void)
  100 {
  101         uint64_t        frequency = 0;
  102         DTEntry         entry;
  103         void            *value;
  104         unsigned int    size;
  105 
  106         if (DTLookupEntry(0, "/efi/platform", &entry) != kSuccess) {
  107                 kprintf("EFI_FSB_frequency: didn't find /efi/platform\n");
  108                 return 0;
  109         }
  110         if (DTGetProperty(entry,FSB_Frequency_prop,&value,&size) != kSuccess) {
  111                 kprintf("EFI_FSB_frequency: property %s not found\n",
  112                         FSB_Frequency_prop);
  113                 return 0;
  114         }
  115         if (size == sizeof(uint64_t)) {
  116                 frequency = *(uint64_t *) value;
  117                 kprintf("EFI_FSB_frequency: read %s value: %llu\n",
  118                         FSB_Frequency_prop, frequency);
  119                 if (!(90*Mega < frequency && frequency < 10*Giga)) {
  120                         kprintf("EFI_FSB_frequency: value out of range\n");
  121                         frequency = 0;
  122                 }
  123         } else {
  124                 kprintf("EFI_FSB_frequency: unexpected size %d\n", size);
  125         }
  126         return frequency;
  127 }
  128 
  129 /*
  130  * Initialize the various conversion factors needed by code referencing
  131  * the TSC.
  132  */
  133 void
  134 tsc_init(void)
  135 {
  136         uint64_t        busFCvtInt = 0;
  137         boolean_t       N_by_2_bus_ratio = FALSE;
  138 
  139         /*
  140          * Get the FSB frequency and conversion factors from EFI.
  141          */
  142         busFreq = EFI_FSB_frequency();
  143 
  144         switch (cpuid_cpufamily()) {
  145         case CPUFAMILY_INTEL_SANDYBRIDGE:
  146         case CPUFAMILY_INTEL_WESTMERE:
  147         case CPUFAMILY_INTEL_NEHALEM: {
  148                 uint64_t cpu_mhz;
  149                 uint64_t msr_flex_ratio;
  150                 uint64_t msr_platform_info;
  151 
  152                 /* See if FLEX_RATIO is being used */
  153                 msr_flex_ratio = rdmsr64(MSR_FLEX_RATIO);
  154                 msr_platform_info = rdmsr64(MSR_PLATFORM_INFO);
  155                 flex_ratio_min = (uint32_t)bitfield(msr_platform_info, 47, 40);
  156                 flex_ratio_max = (uint32_t)bitfield(msr_platform_info, 15, 8);
  157                 /* No BIOS-programed flex ratio. Use hardware max as default */
  158                 tscGranularity = flex_ratio_max;
  159                 if (msr_flex_ratio & bit(16)) {
  160                         /* Flex Enabled: Use this MSR if less than max */
  161                         flex_ratio = (uint32_t)bitfield(msr_flex_ratio, 15, 8);
  162                         if (flex_ratio < flex_ratio_max)
  163                                 tscGranularity = flex_ratio;
  164                 }
  165 
  166                 /* If EFI isn't configured correctly, use a constant 
  167                  * value. See 6036811.
  168                  */
  169                 if (busFreq == 0)
  170                     busFreq = BASE_NHM_CLOCK_SOURCE;
  171 
  172                 cpu_mhz = tscGranularity * BASE_NHM_CLOCK_SOURCE;
  173 
  174                 break;
  175             }
  176         default: {
  177                 uint64_t        prfsts;
  178 
  179                 prfsts = rdmsr64(IA32_PERF_STS);
  180                 tscGranularity = (uint32_t)bitfield(prfsts, 44, 40);
  181                 N_by_2_bus_ratio = (prfsts & bit(46)) != 0;
  182             }
  183         }
  184 
  185         if (busFreq != 0) {
  186                 busFCvtt2n = ((1 * Giga) << 32) / busFreq;
  187                 busFCvtn2t = 0xFFFFFFFFFFFFFFFFULL / busFCvtt2n;
  188                 busFCvtInt = tmrCvt(1 * Peta, 0xFFFFFFFFFFFFFFFFULL / busFreq); 
  189         } else {
  190                 panic("tsc_init: EFI not supported!\n");
  191         }
  192 
  193         kprintf(" BUS: Frequency = %6d.%04dMHz, "
  194                 "cvtt2n = %08X.%08X, cvtn2t = %08X.%08X, "
  195                 "cvtInt = %08X.%08X\n",
  196                 (uint32_t)(busFreq / Mega),
  197                 (uint32_t)(busFreq % Mega), 
  198                 (uint32_t)(busFCvtt2n >> 32), (uint32_t)busFCvtt2n,
  199                 (uint32_t)(busFCvtn2t >> 32), (uint32_t)busFCvtn2t,
  200                 (uint32_t)(busFCvtInt >> 32), (uint32_t)busFCvtInt);
  201 
  202         /*
  203          * Get the TSC increment.  The TSC is incremented by this
  204          * on every bus tick.  Calculate the TSC conversion factors
  205          * to and from nano-seconds.
  206          * The tsc granularity is also called the "bus ratio". If the N/2 bit
  207          * is set this indicates the bus ration is 0.5 more than this - i.e.
  208          * that the true bus ratio is (2*tscGranularity + 1)/2.
  209          */
  210         if (N_by_2_bus_ratio)
  211                 tscFCvtt2n = busFCvtt2n * 2 / (1 + 2*tscGranularity);
  212         else
  213                 tscFCvtt2n = busFCvtt2n / tscGranularity;
  214 
  215         tscFreq = ((1 * Giga)  << 32) / tscFCvtt2n;
  216         tscFCvtn2t = 0xFFFFFFFFFFFFFFFFULL / tscFCvtt2n;
  217 
  218         kprintf(" TSC: Frequency = %6d.%04dMHz, "
  219                 "cvtt2n = %08X.%08X, cvtn2t = %08X.%08X, gran = %lld%s\n",
  220                 (uint32_t)(tscFreq / Mega),
  221                 (uint32_t)(tscFreq % Mega), 
  222                 (uint32_t)(tscFCvtt2n >> 32), (uint32_t)tscFCvtt2n,
  223                 (uint32_t)(tscFCvtn2t >> 32), (uint32_t)tscFCvtn2t,
  224                 tscGranularity, N_by_2_bus_ratio ? " (N/2)" : "");
  225 
  226         /*
  227          * Calculate conversion from BUS to TSC
  228          */
  229         bus2tsc = tmrCvt(busFCvtt2n, tscFCvtn2t);
  230 }
  231 
  232 void
  233 tsc_get_info(tscInfo_t *info)
  234 {
  235         info->busFCvtt2n     = busFCvtt2n;
  236         info->busFCvtn2t     = busFCvtn2t;
  237         info->tscFreq        = tscFreq;
  238         info->tscFCvtt2n     = tscFCvtt2n;
  239         info->tscFCvtn2t     = tscFCvtn2t;
  240         info->tscGranularity = tscGranularity;
  241         info->bus2tsc        = bus2tsc;
  242         info->busFreq        = busFreq;
  243         info->flex_ratio     = flex_ratio;
  244         info->flex_ratio_min = flex_ratio_min;
  245         info->flex_ratio_max = flex_ratio_max;
  246 }

Cache object: a422641ec03945780bb4b417ffb85a8a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.