Merge branches 'x86/alternatives', 'x86/cleanups', 'x86/commandline', 'x86/crashdump...
authorIngo Molnar <mingo@elte.hu>
Mon, 6 Oct 2008 16:17:07 +0000 (18:17 +0200)
committerIngo Molnar <mingo@elte.hu>
Mon, 6 Oct 2008 16:17:07 +0000 (18:17 +0200)
38 files changed:
1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19  20  21 
Documentation/kernel-parameters.txt
arch/x86/Kconfig
arch/x86/boot/compressed/misc.c
arch/x86/kernel/alternative.c
arch/x86/kernel/apm_32.c
arch/x86/kernel/cpu/mtrr/main.c
arch/x86/kernel/crash_dump_64.c
arch/x86/kernel/pci-gart_64.c
arch/x86/kernel/process.c
arch/x86/kernel/process_32.c
arch/x86/kernel/process_64.c
arch/x86/kernel/setup.c
arch/x86/kernel/signal_64.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/sys_x86_64.c
arch/x86/kernel/traps_64.c
arch/x86/kernel/tsc.c
arch/x86/kernel/vmi_32.c
arch/x86/mm/pageattr.c
arch/x86/xen/enlighten.c
include/asm-x86/apic.h
include/asm-x86/asm.h
include/asm-x86/elf.h
include/asm-x86/futex.h
include/asm-x86/gart.h
include/asm-x86/mach-rdc321x/gpio.h
include/asm-x86/mmu.h
include/asm-x86/msr.h
include/asm-x86/nmi.h
include/asm-x86/page_32.h
include/asm-x86/paravirt.h
include/asm-x86/pgtable-2level.h
include/asm-x86/pgtable-3level.h
include/asm-x86/pgtable.h
include/asm-x86/pgtable_32.h
include/asm-x86/pgtable_64.h
include/asm-x86/resume-trace.h
include/asm-x86/spinlock.h

Simple merge
                          Configure maximum number of CPUS and NUMA Nodes for this architecture.
                          If unsure, say N.
                     
 - -   - -    ---   -if MAXSMP
   -                 config NR_CPUS
   -                    int
   -                    default "4096"
   -                 endif
   -                 
   -                 if !MAXSMP
                     config NR_CPUS
 -     - -    ---   -   int
 -     - -    ---   -   default "4096"
 -     - -    ---   -endif
 -     - -    ---   -
 -     - -    ---   -if !MAXSMP
 -     - -    ---   -config NR_CPUS
 - -   - -    ---   -   int "Maximum number of CPUs (2-4096)"
 - -   - -    ---   -   range 2 4096
 + +   + +    +++   +   int "Maximum number of CPUs (2-512)" if !MAXSMP
 + +   + +    +++   +   range 2 512
                        depends on SMP
 + +   + +    +++   +   default "4096" if MAXSMP
                        default "32" if X86_NUMAQ || X86_SUMMIT || X86_BIGSMP || X86_ES7000
                        default "8"
                        help
                          You can safely say Y even if your machine doesn't have MTRRs, you'll
                          just add about 9 KB to your kernel.
                     
------- -------------     See <file:Documentation/mtrr.txt> for more information.
+++++++ +++++++++++++     See <file:Documentation/x86/mtrr.txt> for more information.
                     
                     config MTRR_SANITIZER
------------ --------   bool
++++++++++++ ++++++++   def_bool y
                        prompt "MTRR cleanup support"
                        depends on MTRR
                        help
Simple merge
Simple merge
Simple merge
@@@@@@@@@@@@@@@@@@@@@@ -834,8 -834,8 -834,8 -834,8 -834,8 -834,8 -834,8 -834,8 -834,8 -834,8 -834,8 -834,8 -835,15 -834,8 -834,8 -834,8 -834,8 -834,8 -834,8 -834,8 -834,8 +835,15 @@@@@@@@@@@@@@@@@@@@@@ static int __init enable_mtrr_cleanup_s
                                enable_mtrr_cleanup = 1;
                        return 0;
                     }
 ------------------ -early_param("enble_mtrr_cleanup", enable_mtrr_cleanup_setup);
 ++++++++++++++++++ +early_param("enable_mtrr_cleanup", enable_mtrr_cleanup_setup);
 +++++++++++ ++++++ +
++++++++++++ ++++++++static int __init mtrr_cleanup_debug_setup(char *str)
++++++++++++ ++++++++{
++++++++++++ ++++++++   debug_print = 1;
++++++++++++ ++++++++   return 0;
++++++++++++ ++++++++}
++++++++++++ ++++++++early_param("mtrr_cleanup_debug", mtrr_cleanup_debug_setup);
+                  + 
                     struct var_mtrr_state {
                        unsigned long   range_startk;
                        unsigned long   range_sizek;
                                                (range0_basek + range0_sizek)<<10);
                                state->reg = range_to_mtrr(state->reg, range0_basek,
                                                range0_sizek, MTRR_TYPE_WRBACK);
-   --- - -- -  ---- 
-   --- - -- -  ----    }
-   --- - -- -  ---- 
-   --- - -- -  ----    range_basek = range0_basek + range0_sizek;
-   --- - -- -  ----    range_sizek = chunk_sizek;
------------ --------
-   --- - -- -  ----    if (range_basek + range_sizek > basek &&
-   --- - -- -  ----        range_basek + range_sizek <= (basek + sizek)) {
-   --- - -- -  ----            /* one hole */
-   --- - -- -  ----            second_basek = basek;
-   --- - -- -  ----            second_sizek = range_basek + range_sizek - basek;
                        }
                     
 ---   - -    --    -   range_basek = range0_basek + range0_sizek;
 ---   - -    --    -   range_sizek = chunk_sizek;
 ---   - -    --    -
 ---   - -    --    -   if (range_basek + range_sizek > basek &&
 ---   - -    --    -       range_basek + range_sizek <= (basek + sizek)) {
 ---   - -    --    -           /* one hole */
 ---   - -    --    -           second_basek = basek;
 ---   - -    --    -           second_sizek = range_basek + range_sizek - basek;
 ---   - -    --    -   }
 ---   - -    --    -
------------ --------   /* if last piece, only could one hole near end */
------------ --------   if ((second_basek || !basek) &&
------------ --------       range_sizek - (state->range_sizek - range0_sizek) - second_sizek <
------------ --------       (chunk_sizek >> 1)) {
------------ --------           /*
------------ --------            * one hole in middle (second_sizek is 0) or at end
------------ --------            * (second_sizek is 0 )
------------ --------            */
------------ --------           hole_sizek = range_sizek - (state->range_sizek - range0_sizek)
------------ --------                            - second_sizek;
------------ --------           hole_basek = range_basek + range_sizek - hole_sizek
------------ --------                            - second_sizek;
------------ --------   } else {
------------ --------           /* fallback for big hole, or several holes */
++++++++++++ ++++++++   if (range0_sizek < state->range_sizek) {
++++++++++++ ++++++++           /* need to handle left over */
                                range_sizek = state->range_sizek - range0_sizek;
------------ --------           second_basek = 0;
------------ --------           second_sizek = 0;
++++++++++++ ++++++++
++++++++++++ ++++++++           if (debug_print)
++++++++++++ ++++++++                   printk(KERN_DEBUG "range: %016lx - %016lx\n",
++++++++++++ ++++++++                            range_basek<<10,
++++++++++++ ++++++++                            (range_basek + range_sizek)<<10);
++++++++++++ ++++++++           state->reg = range_to_mtrr(state->reg, range_basek,
++++++++++++ ++++++++                            range_sizek, MTRR_TYPE_WRBACK);
                        }
                     
------------ --------   if (debug_print)
------------ --------           printk(KERN_DEBUG "range: %016lx - %016lx\n", range_basek<<10,
------------ --------                    (range_basek + range_sizek)<<10);
------------ --------   state->reg = range_to_mtrr(state->reg, range_basek, range_sizek,
------------ --------                                    MTRR_TYPE_WRBACK);
                        if (hole_sizek) {
++++++++++++ ++++++++           hole_basek = range_basek - hole_sizek - second_sizek;
                                if (debug_print)
                                        printk(KERN_DEBUG "hole: %016lx - %016lx\n",
------------ --------                            hole_basek<<10, (hole_basek + hole_sizek)<<10);
------------ --------           state->reg = range_to_mtrr(state->reg, hole_basek, hole_sizek,
------------ --------                                            MTRR_TYPE_UNCACHABLE);
------------ --------
++++++++++++ ++++++++                            hole_basek<<10,
++++++++++++ ++++++++                            (hole_basek + hole_sizek)<<10);
++++++++++++ ++++++++           state->reg = range_to_mtrr(state->reg, hole_basek,
++++++++++++ ++++++++                            hole_sizek, MTRR_TYPE_UNCACHABLE);
                        }
                     
                        return second_sizek;
                                num_var_ranges - num[MTRR_NUM_TYPES])
                                return 0;
                     
++++++++++++ ++++++++   /* print original var MTRRs at first, for debugging: */
++++++++++++ ++++++++   printk(KERN_DEBUG "original variable MTRRs\n");
++++++++++++ ++++++++   for (i = 0; i < num_var_ranges; i++) {
++++++++++++ ++++++++           char start_factor = 'K', size_factor = 'K';
++++++++++++ ++++++++           unsigned long start_base, size_base;
++++++++++++ ++++++++
++++++++++++ ++++++++           size_base = range_state[i].size_pfn << (PAGE_SHIFT - 10);
++++++++++++ ++++++++           if (!size_base)
++++++++++++ ++++++++                   continue;
++++++++++++ ++++++++
++++++++++++ ++++++++           size_base = to_size_factor(size_base, &size_factor),
++++++++++++ ++++++++           start_base = range_state[i].base_pfn << (PAGE_SHIFT - 10);
++++++++++++ ++++++++           start_base = to_size_factor(start_base, &start_factor),
++++++++++++ ++++++++           type = range_state[i].type;
++++++++++++ ++++++++
++++++++++++ ++++++++           printk(KERN_DEBUG "reg %d, base: %ld%cB, range: %ld%cB, type %s\n",
++++++++++++ ++++++++                   i, start_base, start_factor,
++++++++++++ ++++++++                   size_base, size_factor,
++++++++++++ ++++++++                   (type == MTRR_TYPE_UNCACHABLE) ? "UC" :
++++++++++++ ++++++++                       ((type == MTRR_TYPE_WRPROT) ? "WP" :
++++++++++++ ++++++++                        ((type == MTRR_TYPE_WRBACK) ? "WB" : "Other"))
++++++++++++ ++++++++                   );
++++++++++++ ++++++++   }
++++++++++++ ++++++++
                        memset(range, 0, sizeof(range));
                        extra_remove_size = 0;
-- ------------------   if (mtrr_tom2) {
-- ------------------           extra_remove_base = 1 << (32 - PAGE_SHIFT);
++ ++++++++++++++++++   extra_remove_base = 1 << (32 - PAGE_SHIFT);
++ ++++++++++++++++++   if (mtrr_tom2)
                                extra_remove_size =
                                        (mtrr_tom2 >> PAGE_SHIFT) - extra_remove_base;
-- ------------------   }
                        nr_range = x86_get_mtrr_mem_range(range, 0, extra_remove_base,
                                                          extra_remove_size);
++++++++++++ ++++++++   /*
++++++++++++ ++++++++    * [0, 1M) should always be coverred by var mtrr with WB
++++++++++++ ++++++++    * and fixed mtrrs should take effective before var mtrr for it
++++++++++++ ++++++++    */
++++++++++++ ++++++++   nr_range = add_range_with_merge(range, nr_range, 0,
++++++++++++ ++++++++                                   (1ULL<<(20 - PAGE_SHIFT)) - 1);
++++++++++++ ++++++++   /* sort the ranges */
++++++++++++ ++++++++   sort(range, nr_range, sizeof(struct res_range), cmp_range, NULL);
++++++++++++ ++++++++
                        range_sums = sum_ranges(range, nr_range);
                        printk(KERN_INFO "total RAM coverred: %ldM\n",
                               range_sums >> (20 - PAGE_SHIFT));
Simple merge
Simple merge
Simple merge
                     #include <asm/tlbflush.h>
                     #include <asm/cpu.h>
                     #include <asm/kdebug.h>
 +++++++ +++ ++++++ +#include <asm/idle.h>
 ++++++++++++++++++++#include <asm/syscalls.h>
 ++++++++++++++++++++#include <asm/smp.h>
                     
                     asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
                     
@@@@@@@@@@@@@@@@@@@@@@ -94,8 -93,7 -93,6 -93,7 -93,6 -93,6 -93,6 -93,6 -93,8 -93,7 -93,6 -93,6 -93,8 -93,6 -93,6 -93,7 -93,6 -93,8 -93,6 -93,8 -93,6 +94,8 @@@@@@@@@@@@@@@@@@@@@@ DECLARE_PER_CPU(int, cpu_state)
                     static inline void play_dead(void)
                     {
                        idle_task_exit();
 - -     -     -        wbinvd();
 +++++++ +++ ++++ + +   c1e_remove_cpu(raw_smp_processor_id());
 +++++++ +++ ++++ + +
                        mb();
                        /* Ack it */
                        __get_cpu_var(cpu_state) = CPU_DEAD;
@@@@@@@@@@@@@@@@@@@@@@ -670,18 -678,6 -670,14 -694,6 -670,18 -670,18 -670,14 -678,6 -670,18 -678,6 -670,14 -670,14 -670,18 -670,18 -678,6 -670,6 -670,14 -670,18 -670,14 -670,18 -678,6 +686,18 @@@@@@@@@@@@@@@@@@@@@@ void __init setup_arch(char **cmdline_p
                     
                        parse_early_param();
                     
 +++  ++ +++  +++ + +#ifdef CONFIG_X86_64
 +++  ++ +++  +++ + +   check_efer();
 +++  ++ +++  +++ + +#endif
 +++  ++ +++  +++ + +
 + +   + +    ++    +#if defined(CONFIG_VMI) && defined(CONFIG_X86_32)
 + +   + +    ++    +   /*
 + +   + +    ++    +    * Must be before kernel pagetables are setup
 + +   + +    ++    +    * or fixmap area is touched.
 + +   + +    ++    +    */
 + +   + +    ++    +   vmi_init();
 + +   + +    ++    +#endif
 + +   + +    ++    +
                        /* after early param, so could get panic from serial */
                        reserve_early_setup_data();
                     
                        return -EFAULT;
                     }
                     
 --------------------/*
 -------------------- * Return -1L or the syscall number that @regs is executing.
 -------------------- */
 --------------------static long current_syscall(struct pt_regs *regs)
 --------------------{
 --------------------   /*
 --------------------    * We always sign-extend a -1 value being set here,
 --------------------    * so this is always either -1L or a syscall number.
 --------------------    */
 --------------------   return regs->orig_ax;
 --------------------}
 --------------------
 --------------------/*
 -------------------- * Return a value that is -EFOO if the system call in @regs->orig_ax
 -------------------- * returned an error.  This only works for @regs from @current.
 -------------------- */
 --------------------static long current_syscall_ret(struct pt_regs *regs)
 --------------------{
 --------------------#ifdef CONFIG_IA32_EMULATION
 --------------------   if (test_thread_flag(TIF_IA32))
 --------------------           /*
 --------------------            * Sign-extend the value so (int)-EFOO becomes (long)-EFOO
 --------------------            * and will match correctly in comparisons.
 --------------------            */
 --------------------           return (int) regs->ax;
 --------------------#endif
 --------------------   return regs->ax;
 --------------------}
 --------------------
                     /*
                      * OK, we're invoking a handler
-- ------------------ */        
++ ++++++++++++++++++ */
                     
                     static int
                     handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
                                 * handler too.
                                 */
                                regs->flags &= ~X86_EFLAGS_TF;
 --------------------           if (test_thread_flag(TIF_SINGLESTEP))
 --------------------                   ptrace_notify(SIGTRAP);
                     
                                spin_lock_irq(&current->sighand->siglock);
-- ------------------           sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
++ ++++++++++++++++++           sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
                                if (!(ka->sa.sa_flags & SA_NODEFER))
-- ------------------                   sigaddset(&current->blocked,sig);
++ ++++++++++++++++++                   sigaddset(&current->blocked, sig);
                                recalc_sigpending();
                                spin_unlock_irq(&current->sighand->siglock);
 ++++++++++++++++++++
 ++++++++++++++++++++           tracehook_signal_handler(sig, info, ka, regs,
 ++++++++++++++++++++                                    test_thread_flag(TIF_SINGLESTEP));
                        }
                     
                        return ret;
Simple merge
                     #include <linux/utsname.h>
                     #include <linux/personality.h>
                     #include <linux/random.h>
++ ++++++++++++++++++#include <linux/uaccess.h>
                     
-- ------------------#include <asm/uaccess.h>
                     #include <asm/ia32.h>
 ++++++++++++++++++++#include <asm/syscalls.h>
                     
-- ------------------asmlinkage long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags,
-- ------------------   unsigned long fd, unsigned long off)
++ ++++++++++++++++++asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
++ ++++++++++++++++++           unsigned long prot, unsigned long flags,
++ ++++++++++++++++++           unsigned long fd, unsigned long off)
                     {
                        long error;
-- ------------------   struct file * file;
++ ++++++++++++++++++   struct file *file;
                     
                        error = -EINVAL;
                        if (off & ~PAGE_MASK)
Simple merge
@@@@@@@@@@@@@@@@@@@@@@ -104,7 -104,7 -104,7 -104,7 -104,7 -104,7 -104,7 -104,7 -104,7 -104,7 -104,7 -104,7 -104,7 -104,7 -104,7 -104,7 -104,7 -104,7 -104,7 -104,7 -104,7 +104,7 @@@@@@@@@@@@@@@@@@@@@@ __setup("notsc", notsc_setup)
                     /*
                      * Read TSC and the reference counters. Take care of SMI disturbance
                      */
- - ----- ----- -- --static u64 tsc_read_refs(u64 *pm, u64 *hpet)
 - -     -     -     static u64 __init tsc_read_refs(u64 *pm, u64 *hpet)
++++++++++++++++++ ++static u64 tsc_read_refs(u64 *p, int hpet)
                     {
                        u64 t1, t2;
                        int i;
                        return ULLONG_MAX;
                     }
                     
 - -   - --   ---   -/**
 - -   - --   ---   - * native_calibrate_tsc - calibrate the tsc on boot
++++++++++++++++++ ++/*
++++++++++++++++++ ++ * Calculate the TSC frequency from HPET reference
+ + +++ +  +++   + +  */
 - -   - --   ---   -unsigned long native_calibrate_tsc(void)
++++++++++++++++++ ++static unsigned long calc_hpet_ref(u64 deltatsc, u64 hpet1, u64 hpet2)
+ + +++ +  +++   + + {
 - -   - --   ---   -   unsigned long flags;
 - -   - --   ---   -   u64 tsc1, tsc2, tr1, tr2, delta, pm1, pm2, hpet1, hpet2;
 - -   - --   ---   -   int hpet = is_hpet_enabled();
 - -   - --   ---   -   unsigned int tsc_khz_val = 0;
++++++++++++++++++ ++   u64 tmp;
+ + +++ +  +++   + + 
 - -   - --   ---   -   local_irq_save(flags);
++++++++++++++++++ ++   if (hpet2 < hpet1)
++++++++++++++++++ ++           hpet2 += 0x100000000ULL;
++++++++++++++++++ ++   hpet2 -= hpet1;
++++++++++++++++++ ++   tmp = ((u64)hpet2 * hpet_readl(HPET_PERIOD));
++++++++++++++++++ ++   do_div(tmp, 1000000);
++++++++++++++++++ ++   do_div(deltatsc, tmp);
++++++++++++++++++ ++
++++++++++++++++++ ++   return (unsigned long) deltatsc;
++++++++++++++++++ ++}
++++++++++++++++++ ++
++++++++++++++++++ ++/*
++++++++++++++++++ ++ * Calculate the TSC frequency from PMTimer reference
++++++++++++++++++ ++ */
++++++++++++++++++ ++static unsigned long calc_pmtimer_ref(u64 deltatsc, u64 pm1, u64 pm2)
++++++++++++++++++ ++{
++++++++++++++++++ ++   u64 tmp;
+ + +++ + ++++   + + 
 - -   - -    ---   -   tsc1 = tsc_read_refs(&pm1, hpet ? &hpet1 : NULL);
++++++++++++++++++ ++   if (!pm1 && !pm2)
++++++++++++++++++ ++           return ULONG_MAX;
++++++++++++++++++ ++
++++++++++++++++++ ++   if (pm2 < pm1)
++++++++++++++++++ ++           pm2 += (u64)ACPI_PM_OVRRUN;
++++++++++++++++++ ++   pm2 -= pm1;
++++++++++++++++++ ++   tmp = pm2 * 1000000000LL;
++++++++++++++++++ ++   do_div(tmp, PMTMR_TICKS_PER_SEC);
++++++++++++++++++ ++   do_div(deltatsc, tmp);
++++++++++++++++++ ++
++++++++++++++++++ ++   return (unsigned long) deltatsc;
++++++++++++++++++ ++}
++++++++++++++++++ ++
++++++++++++++++++ ++#define CAL_MS             10
++++++++++++++++++ ++#define CAL_LATCH  (CLOCK_TICK_RATE / (1000 / CAL_MS))
++++++++++++++++++ ++#define CAL_PIT_LOOPS      1000
++++++++++++++++++ ++
++++++++++++++++++ ++#define CAL2_MS            50
++++++++++++++++++ ++#define CAL2_LATCH (CLOCK_TICK_RATE / (1000 / CAL2_MS))
++++++++++++++++++ ++#define CAL2_PIT_LOOPS     5000
++++++++++++++++++ ++
++++++++++++++++++ ++
 + +   + ++   +++   +/*
 + +   + ++   +++   + * Try to calibrate the TSC against the Programmable
 + +   + ++   +++   + * Interrupt Timer and return the frequency of the TSC
 + +   + ++   +++   + * in kHz.
 + +   + ++   +++   + *
 + +   + ++   +++   + * Return ULONG_MAX on failure to calibrate.
 + +   + ++   +++   + */
- - --- -  ---   - - static unsigned long pit_calibrate_tsc(void)
++++++++++++++++++ ++static unsigned long pit_calibrate_tsc(u32 latch, unsigned long ms, int loopmin)
 + +   + ++   +++   +{
 + +   + ++   +++   +   u64 tsc, t1, t2, delta;
 + +   + ++   +++   +   unsigned long tscmin, tscmax;
 + +   + ++   +++   +   int pitcnt;
          +          
 + +   + ++   +++   +   /* Set the Gate high, disable speaker */
          +             outb((inb(0x61) & ~0x02) | 0x01, 0x61);
          +          
 + +   + ++   +++   +   /*
 + +   + ++   +++   +    * Setup CTC channel 2* for mode 0, (interrupt on terminal
 + +   + ++   +++   +    * count mode), binary count. Set the latch register to 50ms
 + +   + ++   +++   +    * (LSB then MSB) to begin countdown.
 + +   + ++   +++   +    */
          +             outb(0xb0, 0x43);
---------- ------- --   outb((CLOCK_TICK_RATE / (1000 / 50)) & 0xff, 0x42);
---------- ------- --   outb((CLOCK_TICK_RATE / (1000 / 50)) >> 8, 0x42);
 - -   - -    ---   -   tr1 = get_cycles();
 - -   - -    ---   -   while ((inb(0x61) & 0x20) == 0);
 - -   - -    ---   -   tr2 = get_cycles();
++++++++++++++++++ ++   outb(latch & 0xff, 0x42);
++++++++++++++++++ ++   outb(latch >> 8, 0x42);
          +          
 - -   - -    ---   -   tsc2 = tsc_read_refs(&pm2, hpet ? &hpet2 : NULL);
 + +   + ++   +++   +   tsc = t1 = t2 = get_cycles();
 + +   + ++   +++   +
 + +   + ++   +++   +   pitcnt = 0;
 + +   + ++   +++   +   tscmax = 0;
 + +   + ++   +++   +   tscmin = ULONG_MAX;
 + +   + ++   +++   +   while ((inb(0x61) & 0x20) == 0) {
 + +   + ++   +++   +           t2 = get_cycles();
 + +   + ++   +++   +           delta = t2 - tsc;
 + +   + ++   +++   +           tsc = t2;
 + +   + ++   +++   +           if ((unsigned long) delta < tscmin)
 + +   + ++   +++   +                   tscmin = (unsigned int) delta;
 + +   + ++   +++   +           if ((unsigned long) delta > tscmax)
 + +   + ++   +++   +                   tscmax = (unsigned int) delta;
 + +   + ++   +++   +           pitcnt++;
 + +   + ++   +++   +   }
 + +   + ++   +++   +
 + +   + ++   +++   +   /*
 + +   + ++   +++   +    * Sanity checks:
 + +   + ++   +++   +    *
- - --- -  ---   - -     * If we were not able to read the PIT more than 5000
++++++++++++++++++ ++    * If we were not able to read the PIT more than loopmin
 + +   + ++   +++   +    * times, then we have been hit by a massive SMI
 + +   + ++   +++   +    *
 + +   + ++   +++   +    * If the maximum is 10 times larger than the minimum,
 + +   + ++   +++   +    * then we got hit by an SMI as well.
 + +   + ++   +++   +    */
- - --- -  ---   - -    if (pitcnt < 5000 || tscmax > 10 * tscmin)
++++++++++++++++++ ++   if (pitcnt < loopmin || tscmax > 10 * tscmin)
 + +   + ++   +++   +           return ULONG_MAX;
 + +   + ++   +++   +
 + +   + ++   +++   +   /* Calculate the PIT value */
 + +   + ++   +++   +   delta = t2 - t1;
- - --- -  ---   - -    do_div(delta, 50);
++++++++++++++++++ ++   do_div(delta, ms);
 + +   + ++   +++   +   return delta;
 + +   + ++   +++   +}
          +          
++++++++++++++++++ ++/*
++++++++++++++++++ ++ * This reads the current MSB of the PIT counter, and
++++++++++++++++++ ++ * checks if we are running on sufficiently fast and
++++++++++++++++++ ++ * non-virtualized hardware.
++++++++++++++++++ ++ *
++++++++++++++++++ ++ * Our expectations are:
++++++++++++++++++ ++ *
++++++++++++++++++ ++ *  - the PIT is running at roughly 1.19MHz
++++++++++++++++++ ++ *
++++++++++++++++++ ++ *  - each IO is going to take about 1us on real hardware,
++++++++++++++++++ ++ *    but we allow it to be much faster (by a factor of 10) or
++++++++++++++++++ ++ *    _slightly_ slower (ie we allow up to a 2us read+counter
++++++++++++++++++ ++ *    update - anything else implies a unacceptably slow CPU
++++++++++++++++++ ++ *    or PIT for the fast calibration to work.
++++++++++++++++++ ++ *
++++++++++++++++++ ++ *  - with 256 PIT ticks to read the value, we have 214us to
++++++++++++++++++ ++ *    see the same MSB (and overhead like doing a single TSC
++++++++++++++++++ ++ *    read per MSB value etc).
++++++++++++++++++ ++ *
++++++++++++++++++ ++ *  - We're doing 2 reads per loop (LSB, MSB), and we expect
++++++++++++++++++ ++ *    them each to take about a microsecond on real hardware.
++++++++++++++++++ ++ *    So we expect a count value of around 100. But we'll be
++++++++++++++++++ ++ *    generous, and accept anything over 50.
++++++++++++++++++ ++ *
++++++++++++++++++ ++ *  - if the PIT is stuck, and we see *many* more reads, we
++++++++++++++++++ ++ *    return early (and the next caller of pit_expect_msb()
++++++++++++++++++ ++ *    then consider it a failure when they don't see the
++++++++++++++++++ ++ *    next expected value).
++++++++++++++++++ ++ *
++++++++++++++++++ ++ * These expectations mean that we know that we have seen the
++++++++++++++++++ ++ * transition from one expected value to another with a fairly
++++++++++++++++++ ++ * high accuracy, and we didn't miss any events. We can thus
++++++++++++++++++ ++ * use the TSC value at the transitions to calculate a pretty
++++++++++++++++++ ++ * good value for the TSC frequencty.
++++++++++++++++++ ++ */
++++++++++++++++++ ++static inline int pit_expect_msb(unsigned char val)
++++++++++++++++++ ++{
++++++++++++++++++ ++   int count = 0;
++++++++++ +++++++ ++
          -             tsc1 = tsc_read_refs(&pm1, hpet ? &hpet1 : NULL);
++++++++++++++++++ ++   for (count = 0; count < 50000; count++) {
++++++++++++++++++ ++           /* Ignore LSB */
++++++++++++++++++ ++           inb(0x42);
++++++++++++++++++ ++           if (inb(0x42) != val)
++++++++++++++++++ ++                   break;
++++++++++++++++++ ++   }
++++++++++++++++++ ++   return count > 50;
++++++++++++++++++ ++}
++++++++++++++++++ ++
++++++++++++++++++ ++/*
++++++++++++++++++ ++ * How many MSB values do we want to see? We aim for a
++++++++++++++++++ ++ * 15ms calibration, which assuming a 2us counter read
++++++++++++++++++ ++ * error should give us roughly 150 ppm precision for
++++++++++++++++++ ++ * the calibration.
++++++++++++++++++ ++ */
++++++++++++++++++ ++#define QUICK_PIT_MS 15
++++++++++++++++++ ++#define QUICK_PIT_ITERATIONS (QUICK_PIT_MS * PIT_TICK_RATE / 1000 / 256)
++++++++++ +++++++ ++
++++++++++++++++++ ++static unsigned long quick_pit_calibrate(void)
++++++++++++++++++ ++{
++++++++++++++++++ ++   /* Set the Gate high, disable speaker */
++++++++++ +++++++ ++   outb((inb(0x61) & ~0x02) | 0x01, 0x61);
++++++++++ +++++++ ++
++++++++++++++++++ ++   /*
++++++++++++++++++ ++    * Counter 2, mode 0 (one-shot), binary count
++++++++++++++++++ ++    *
++++++++++++++++++ ++    * NOTE! Mode 2 decrements by two (and then the
++++++++++++++++++ ++    * output is flipped each time, giving the same
++++++++++++++++++ ++    * final output frequency as a decrement-by-one),
++++++++++++++++++ ++    * so mode 0 is much better when looking at the
++++++++++++++++++ ++    * individual counts.
++++++++++++++++++ ++    */
++++++++++ +++++++ ++   outb(0xb0, 0x43);
          -             outb((CLOCK_TICK_RATE / (1000 / 50)) & 0xff, 0x42);
          -             outb((CLOCK_TICK_RATE / (1000 / 50)) >> 8, 0x42);
          -             tr1 = get_cycles();
          -             while ((inb(0x61) & 0x20) == 0);
          -             tr2 = get_cycles();
++++++++++ +++++++ ++
          -             tsc2 = tsc_read_refs(&pm2, hpet ? &hpet2 : NULL);
++++++++++++++++++ ++   /* Start at 0xffff */
++++++++++++++++++ ++   outb(0xff, 0x42);
++++++++++++++++++ ++   outb(0xff, 0x42);
++++++++++++++++++ ++
++++++++++++++++++ ++   if (pit_expect_msb(0xff)) {
++++++++++++++++++ ++           int i;
++++++++++++++++++ ++           u64 t1, t2, delta;
++++++++++++++++++ ++           unsigned char expect = 0xfe;
++++++++++++++++++ ++
++++++++++++++++++ ++           t1 = get_cycles();
++++++++++++++++++ ++           for (i = 0; i < QUICK_PIT_ITERATIONS; i++, expect--) {
++++++++++++++++++ ++                   if (!pit_expect_msb(expect))
++++++++++++++++++ ++                           goto failed;
++++++++++++++++++ ++           }
++++++++++++++++++ ++           t2 = get_cycles();
++++++++++++++++++ ++
++++++++++++++++++ ++           /*
++++++++++++++++++ ++            * Make sure we can rely on the second TSC timestamp:
++++++++++++++++++ ++            */
++++++++++++++++++ ++           if (!pit_expect_msb(expect))
++++++++++++++++++ ++                   goto failed;
++++++++++++++++++ ++
++++++++++++++++++ ++           /*
++++++++++++++++++ ++            * Ok, if we get here, then we've seen the
++++++++++++++++++ ++            * MSB of the PIT decrement QUICK_PIT_ITERATIONS
++++++++++++++++++ ++            * times, and each MSB had many hits, so we never
++++++++++++++++++ ++            * had any sudden jumps.
++++++++++++++++++ ++            *
++++++++++++++++++ ++            * As a result, we can depend on there not being
++++++++++++++++++ ++            * any odd delays anywhere, and the TSC reads are
++++++++++++++++++ ++            * reliable.
++++++++++++++++++ ++            *
++++++++++++++++++ ++            * kHz = ticks / time-in-seconds / 1000;
++++++++++++++++++ ++            * kHz = (t2 - t1) / (QPI * 256 / PIT_TICK_RATE) / 1000
++++++++++++++++++ ++            * kHz = ((t2 - t1) * PIT_TICK_RATE) / (QPI * 256 * 1000)
++++++++++++++++++ ++            */
++++++++++++++++++ ++           delta = (t2 - t1)*PIT_TICK_RATE;
++++++++++++++++++ ++           do_div(delta, QUICK_PIT_ITERATIONS*256*1000);
++++++++++++++++++ ++           printk("Fast TSC calibration using PIT\n");
++++++++++++++++++ ++           return delta;
++++++++++++++++++ ++   }
++++++++++++++++++ ++failed:
++++++++++++++++++ ++   return 0;
++++++++++++++++++ ++}
 + +   + +    +++   +
 + +   + ++   +++   +/**
 + +   + ++   +++   + * native_calibrate_tsc - calibrate the tsc on boot
 + +   + ++   +++   + */
 + +   + ++   +++   +unsigned long native_calibrate_tsc(void)
 + +   + ++   +++   +{
- - --- -  ---   - -    u64 tsc1, tsc2, delta, pm1, pm2, hpet1, hpet2;
++++++++++++++++++ ++   u64 tsc1, tsc2, delta, ref1, ref2;
 + +   + ++   +++   +   unsigned long tsc_pit_min = ULONG_MAX, tsc_ref_min = ULONG_MAX;
- - --- -  ---   - -    unsigned long flags;
- - --- -  ---   - -    int hpet = is_hpet_enabled(), i;
++++++++++++++++++ ++   unsigned long flags, latch, ms, fast_calibrate;
++++++++++++++++++ ++   int hpet = is_hpet_enabled(), i, loopmin;
++++++++++++++++++ ++
++++++++++++++++++ ++   local_irq_save(flags);
++++++++++++++++++ ++   fast_calibrate = quick_pit_calibrate();
+ + +++ +  +++   + +    local_irq_restore(flags);
++++++++++++++++++ ++   if (fast_calibrate)
++++++++++++++++++ ++           return fast_calibrate;
                     
                        /*
 - -   - --   ---   -    * Preset the result with the raw and inaccurate PIT
 - -   - --   ---   -    * calibration value
 + +   + ++   +++   +    * Run 5 calibration loops to get the lowest frequency value
 + +   + ++   +++   +    * (the best estimate). We use two different calibration modes
 + +   + ++   +++   +    * here:
 + +   + ++   +++   +    *
 + +   + ++   +++   +    * 1) PIT loop. We set the PIT Channel 2 to oneshot mode and
 + +   + ++   +++   +    * load a timeout of 50ms. We read the time right after we
 + +   + ++   +++   +    * started the timer and wait until the PIT count down reaches
 + +   + ++   +++   +    * zero. In each wait loop iteration we read the TSC and check
 + +   + ++   +++   +    * the delta to the previous read. We keep track of the min
 + +   + ++   +++   +    * and max values of that delta. The delta is mostly defined
 + +   + ++   +++   +    * by the IO time of the PIT access, so we can detect when a
 + +   + ++   +++   +    * SMI/SMM disturbance happend between the two reads. If the
 + +   + ++   +++   +    * maximum time is significantly larger than the minimum time,
 + +   + ++   +++   +    * then we discard the result and have another try.
 + +   + ++   +++   +    *
 + +   + ++   +++   +    * 2) Reference counter. If available we use the HPET or the
 + +   + ++   +++   +    * PMTIMER as a reference to check the sanity of that value.
 + +   + ++   +++   +    * We use separate TSC readouts and check inside of the
 + +   + ++   +++   +    * reference read for a SMI/SMM disturbance. We dicard
 + +   + ++   +++   +    * disturbed values here as well. We do that around the PIT
 + +   + ++   +++   +    * calibration delay loop as we have to wait for a certain
 + +   + ++   +++   +    * amount of time anyway.
                         */
- - --- -  ---   - -    for (i = 0; i < 5; i++) {
 - -   - --   ---   -   delta = (tr2 - tr1);
 - -   - --   ---   -   do_div(delta, 50);
 - -   - --   ---   -   tsc_khz_val = delta;
 - -   - --   ---   -
 - -   - --   ---   -   /* hpet or pmtimer available ? */
 - -   - --   ---   -   if (!hpet && !pm1 && !pm2) {
 - -   - --   ---   -           printk(KERN_INFO "TSC calibrated against PIT\n");
 - -   - --   ---   -           goto out;
++++++++++++++++++ ++
++++++++++++++++++ ++   /* Preset PIT loop values */
++++++++++++++++++ ++   latch = CAL_LATCH;
++++++++++++++++++ ++   ms = CAL_MS;
++++++++++++++++++ ++   loopmin = CAL_PIT_LOOPS;
++++++++++++++++++ ++
++++++++++++++++++ ++   for (i = 0; i < 3; i++) {
 + +   + ++   +++   +           unsigned long tsc_pit_khz;
 + +   + ++   +++   +
 + +   + ++   +++   +           /*
 + +   + ++   +++   +            * Read the start value and the reference count of
 + +   + ++   +++   +            * hpet/pmtimer when available. Then do the PIT
 + +   + ++   +++   +            * calibration, which will take at least 50ms, and
 + +   + ++   +++   +            * read the end value.
 + +   + ++   +++   +            */
 + +   + ++   +++   +           local_irq_save(flags);
- - --- -  ---   - -            tsc1 = tsc_read_refs(&pm1, hpet ? &hpet1 : NULL);
- - --- -  ---   - -            tsc_pit_khz = pit_calibrate_tsc();
- - --- -  ---   - -            tsc2 = tsc_read_refs(&pm2, hpet ? &hpet2 : NULL);
++++++++++++++++++ ++           tsc1 = tsc_read_refs(&ref1, hpet);
++++++++++++++++++ ++           tsc_pit_khz = pit_calibrate_tsc(latch, ms, loopmin);
++++++++++++++++++ ++           tsc2 = tsc_read_refs(&ref2, hpet);
 + +   + ++   +++   +           local_irq_restore(flags);
 + +   + ++   +++   +
 + +   + ++   +++   +           /* Pick the lowest PIT TSC calibration so far */
 + +   + ++   +++   +           tsc_pit_min = min(tsc_pit_min, tsc_pit_khz);
 + +   + ++   +++   +
 + +   + ++   +++   +           /* hpet or pmtimer available ? */
- - --- -  ---   - -            if (!hpet && !pm1 && !pm2)
++++++++++++++++++ ++           if (!hpet && !ref1 && !ref2)
 + +   + ++   +++   +                   continue;
 + +   + ++   +++   +
 + +   + ++   +++   +           /* Check, whether the sampling was disturbed by an SMI */
 + +   + ++   +++   +           if (tsc1 == ULLONG_MAX || tsc2 == ULLONG_MAX)
 + +   + ++   +++   +                   continue;
 + +   + ++   +++   +
 + +   + ++   +++   +           tsc2 = (tsc2 - tsc1) * 1000000LL;
++++++++++++++++++ ++           if (hpet)
++++++++++++++++++ ++                   tsc2 = calc_hpet_ref(tsc2, ref1, ref2);
++++++++++++++++++ ++           else
++++++++++++++++++ ++                   tsc2 = calc_pmtimer_ref(tsc2, ref1, ref2);
 + +   + ++   +++   +
- - --- -  ---   - -            if (hpet) {
- - --- -  ---   - -                    if (hpet2 < hpet1)
- - --- -  ---   - -                            hpet2 += 0x100000000ULL;
- - --- -  ---   - -                    hpet2 -= hpet1;
- - --- -  ---   - -                    tsc1 = ((u64)hpet2 * hpet_readl(HPET_PERIOD));
- - --- -  ---   - -                    do_div(tsc1, 1000000);
- - --- -  ---   - -            } else {
- - --- -  ---   - -                    if (pm2 < pm1)
- - --- -  ---   - -                            pm2 += (u64)ACPI_PM_OVRRUN;
- - --- -  ---   - -                    pm2 -= pm1;
- - --- -  ---   - -                    tsc1 = pm2 * 1000000000LL;
- - --- -  ---   - -                    do_div(tsc1, PMTMR_TICKS_PER_SEC);
++++++++++++++++++ ++           tsc_ref_min = min(tsc_ref_min, (unsigned long) tsc2);
++++++++++++++++++ ++
++++++++++++++++++ ++           /* Check the reference deviation */
++++++++++++++++++ ++           delta = ((u64) tsc_pit_min) * 100;
++++++++++++++++++ ++           do_div(delta, tsc_ref_min);
++++++++++++++++++ ++
++++++++++++++++++ ++           /*
++++++++++++++++++ ++            * If both calibration results are inside a 10% window
++++++++++++++++++ ++            * then we can be sure, that the calibration
++++++++++++++++++ ++            * succeeded. We break out of the loop right away. We
++++++++++++++++++ ++            * use the reference value, as it is more precise.
++++++++++++++++++ ++            */
++++++++++++++++++ ++           if (delta >= 90 && delta <= 110) {
++++++++++++++++++ ++                   printk(KERN_INFO
++++++++++++++++++ ++                          "TSC: PIT calibration matches %s. %d loops\n",
++++++++++++++++++ ++                          hpet ? "HPET" : "PMTIMER", i + 1);
++++++++++++++++++ ++                   return tsc_ref_min;
 + +   + ++   +++   +           }
 + +   + ++   +++   +
- - --- -  ---   - -            do_div(tsc2, tsc1);
- - --- -  ---   - -            tsc_ref_min = min(tsc_ref_min, (unsigned long) tsc2);
++++++++++++++++++ ++           /*
++++++++++++++++++ ++            * Check whether PIT failed more than once. This
++++++++++++++++++ ++            * happens in virtualized environments. We need to
++++++++++++++++++ ++            * give the virtual PC a slightly longer timeframe for
++++++++++++++++++ ++            * the HPET/PMTIMER to make the result precise.
++++++++++++++++++ ++            */
++++++++++++++++++ ++           if (i == 1 && tsc_pit_min == ULONG_MAX) {
++++++++++++++++++ ++                   latch = CAL2_LATCH;
++++++++++++++++++ ++                   ms = CAL2_MS;
++++++++++++++++++ ++                   loopmin = CAL2_PIT_LOOPS;
++++++++++++++++++ ++           }
                        }
                     
 - -   - --   ---   -   /* Check, whether the sampling was disturbed by an SMI */
 - -   - --   ---   -   if (tsc1 == ULLONG_MAX || tsc2 == ULLONG_MAX) {
 - -   - --   ---   -           printk(KERN_WARNING "TSC calibration disturbed by SMI, "
 - -   - --   ---   -                           "using PIT calibration result\n");
 - -   - --   ---   -           goto out;
 + +   + ++   +++   +   /*
 + +   + ++   +++   +    * Now check the results.
 + +   + ++   +++   +    */
 + +   + ++   +++   +   if (tsc_pit_min == ULONG_MAX) {
 + +   + ++   +++   +           /* PIT gave no useful value */
                  -             printk(KERN_WARNING "TSC: PIT calibration failed due to "
                  -                    "SMI disturbance.\n");
 + +   + ++   +++ + +           printk(KERN_WARNING "TSC: Unable to calibrate against PIT\n");
 + +   + ++   +++   +
 + +   + ++   +++   +           /* We don't have an alternative source, disable TSC */
- - --- -  ---   - -            if (!hpet && !pm1 && !pm2) {
++++++++++++++++++ ++           if (!hpet && !ref1 && !ref2) {
 + +   + ++   +++   +                   printk("TSC: No reference (HPET/PMTIMER) available\n");
 + +   + ++   +++   +                   return 0;
 + +   + ++   +++   +           }
 + +   + ++   +++   +
 + +   + ++   +++   +           /* The alternative source failed as well, disable TSC */
 + +   + ++   +++   +           if (tsc_ref_min == ULONG_MAX) {
 + +   + ++   +++   +                   printk(KERN_WARNING "TSC: HPET/PMTIMER calibration "
- - --- -  ---   - -                           "failed due to SMI disturbance.\n");
++++++++++++++++++ ++                          "failed.\n");
 + +   + ++   +++   +                   return 0;
 + +   + ++   +++   +           }
 + +   + ++   +++   +
 + +   + ++   +++   +           /* Use the alternative source */
 + +   + ++   +++   +           printk(KERN_INFO "TSC: using %s reference calibration\n",
 + +   + ++   +++   +                  hpet ? "HPET" : "PMTIMER");
 + +   + ++   +++   +
 + +   + ++   +++   +           return tsc_ref_min;
                        }
                     
 - -   - --   ---   -   tsc2 = (tsc2 - tsc1) * 1000000LL;
 - -   - --   ---   -
 - -   - --   ---   -   if (hpet) {
 - -   - --   ---   -           printk(KERN_INFO "TSC calibrated against HPET\n");
 - -   - --   ---   -           if (hpet2 < hpet1)
 - -   - --   ---   -                   hpet2 += 0x100000000ULL;
 - -   - --   ---   -           hpet2 -= hpet1;
 - -   - --   ---   -           tsc1 = ((u64)hpet2 * hpet_readl(HPET_PERIOD));
 - -   - --   ---   -           do_div(tsc1, 1000000);
 - -   - --   ---   -   } else {
 - -   - --   ---   -           printk(KERN_INFO "TSC calibrated against PM_TIMER\n");
 - -   - --   ---   -           if (pm2 < pm1)
 - -   - --   ---   -                   pm2 += (u64)ACPI_PM_OVRRUN;
 - -   - --   ---   -           pm2 -= pm1;
 - -   - --   ---   -           tsc1 = pm2 * 1000000000LL;
 - -   - --   ---   -           do_div(tsc1, PMTMR_TICKS_PER_SEC);
 + +   + ++   +++   +   /* We don't have an alternative source, use the PIT calibration value */
- - --- -  ---   - -    if (!hpet && !pm1 && !pm2) {
++++++++++++++++++ ++   if (!hpet && !ref1 && !ref2) {
 + +   + ++   +++   +           printk(KERN_INFO "TSC: Using PIT calibration value\n");
 + +   + ++   +++   +           return tsc_pit_min;
                        }
                     
 - -   - --   ---   -   do_div(tsc2, tsc1);
 - -   - --   ---   -   tsc_khz_val = tsc2;
 + +   + ++   +++   +   /* The alternative source failed, use the PIT calibration value */
 + +   + ++   +++   +   if (tsc_ref_min == ULONG_MAX) {
- - --- -  ---   - -            printk(KERN_WARNING "TSC: HPET/PMTIMER calibration failed due "
- - --- -  ---   - -                   "to SMI disturbance. Using PIT calibration\n");
++++++++++++++++++ ++           printk(KERN_WARNING "TSC: HPET/PMTIMER calibration failed. "
++++++++++++++++++ ++                  "Using PIT calibration\n");
 + +   + ++   +++   +           return tsc_pit_min;
 + +   + ++   +++   +   }
                     
- - --- -  ---   - -    /* Check the reference deviation */
- - --- -  ---   - -    delta = ((u64) tsc_pit_min) * 100;
- - --- -  ---   - -    do_div(delta, tsc_ref_min);
- - --- -  ---   - - 
- - --- -  ---   - -    /*
- - --- -  ---   - -     * If both calibration results are inside a 5% window, the we
- - --- -  ---   - -     * use the lower frequency of those as it is probably the
- - --- -  ---   - -     * closest estimate.
- - --- -  ---   - -     */
- - --- -  ---   - -    if (delta >= 95 && delta <= 105) {
- - --- -  ---   - -            printk(KERN_INFO "TSC: PIT calibration confirmed by %s.\n",
- - --- -  ---   - -                   hpet ? "HPET" : "PMTIMER");
- - --- -  ---   - -            printk(KERN_INFO "TSC: using %s calibration value\n",
- - --- -  ---   - -                   tsc_pit_min <= tsc_ref_min ? "PIT" :
- - --- -  ---   - -                   hpet ? "HPET" : "PMTIMER");
- - --- -  ---   - -            return tsc_pit_min <= tsc_ref_min ? tsc_pit_min : tsc_ref_min;
- - --- -  ---   - -    }
- - --- -  ---   - - 
- - --- -  ---   - -    printk(KERN_WARNING "TSC: PIT calibration deviates from %s: %lu %lu.\n",
- - --- -  ---   - -           hpet ? "HPET" : "PMTIMER", tsc_pit_min, tsc_ref_min);
- - --- -  ---   - - 
 - -   - --   ---   -out:
 - -   - --   ---   -   return tsc_khz_val;
 + +   + ++   +++   +   /*
 + +   + ++   +++   +    * The calibration values differ too much. In doubt, we use
 + +   + ++   +++   +    * the PIT value as we know that there are PMTIMERs around
- - --- -  ---   - -     * running at double speed.
++++++++++++++++++ ++    * running at double speed. At least we let the user know:
 + +   + ++   +++   +    */
++++++++++++++++++ ++   printk(KERN_WARNING "TSC: PIT calibration deviates from %s: %lu %lu.\n",
++++++++++++++++++ ++          hpet ? "HPET" : "PMTIMER", tsc_pit_min, tsc_ref_min);
 + +   + ++   +++   +   printk(KERN_INFO "TSC: Using PIT calibration value\n");
 + +   + ++   +++   +   return tsc_pit_min;
                     }
                     
 - -   - --   ---   -
                     #ifdef CONFIG_X86_32
                     /* Only called from the Powernow K7 cpu freq driver */
                     int recalibrate_cpu_khz(void)
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@@@@@@@@@@@@@@@@@@@@ -1,6 -1,6 -1,6 -1,6 -1,6 -1,8 -1,6 -1,6 -1,6 -1,6 -1,6 -1,6 -1,6 -1,6 -1,6 -1,6 -1,6 -1,6 -1,6 -1,6 -1,6 +1,8 @@@@@@@@@@@@@@@@@@@@@@
 --------------------#ifndef _RDC321X_GPIO_H
 --------------------#define _RDC321X_GPIO_H
 ++++++++++++++++++++#ifndef ASM_X86__MACH_RDC321X__GPIO_H
 ++++++++++++++++++++#define ASM_X86__MACH_RDC321X__GPIO_H
 ++++ +++++++++++++++
+++++ +++++++++++++++#include <linux/kernel.h>
+                    
                     extern int rdc_gpio_get_value(unsigned gpio);
                     extern void rdc_gpio_set_value(unsigned gpio, int value);
                     extern int rdc_gpio_direction_input(unsigned gpio);
Simple merge
@@@@@@@@@@@@@@@@@@@@@@ -52,17 -52,17 -52,17 -52,17 -52,17 -52,33 -52,17 -52,17 -52,17 -52,17 -52,17 -52,17 -52,17 -52,17 -52,17 -52,17 -52,17 -52,17 -52,17 -52,17 -52,17 +52,33 @@@@@@@@@@@@@@@@@@@@@@ static inline unsigned long long native
                     {
                        DECLARE_ARGS(val, low, high);
                     
 - -   - --   ---   -                : "c" (msr), "i" (-EFAULT));
 + +   + ++   +++   +   asm volatile("2: rdmsr ; xor %[err],%[err]\n"
 + +   + ++   +++   +                "1:\n\t"
 + +   + ++   +++   +                ".section .fixup,\"ax\"\n\t"
 + +   + ++   +++   +                "3:  mov %[fault],%[err] ; jmp 1b\n\t"
 + +   + ++   +++   +                ".previous\n\t"
 + +   + ++   +++   +                _ASM_EXTABLE(2b, 3b)
 + +   + ++   +++   +                : [err] "=r" (*err), EAX_EDX_RET(val, low, high)
 + +   + ++   +++   +                : "c" (msr), [fault] "i" (-EFAULT));
 + +   + ++   +++   +   return EAX_EDX_VAL(val, low, high);
 + +   + ++   +++   +}
 + +   + ++   +++   +
+++++ +++++++++++++++static inline unsigned long long native_read_msr_amd_safe(unsigned int msr,
+++++ +++++++++++++++                                                 int *err)
+++++ +++++++++++++++{
+++++ +++++++++++++++   DECLARE_ARGS(val, low, high);
+++++ +++++++++++++++
+ + + + +  +++   +++    asm volatile("2: rdmsr ; xor %0,%0\n"
+ + + + +  +++   +++                 "1:\n\t"
+ + + + +  +++   +++                 ".section .fixup,\"ax\"\n\t"
+ + + + +  +++   +++                 "3:  mov %3,%0 ; jmp 1b\n\t"
+ + + + +  +++   +++                 ".previous\n\t"
+ + + + +  +++   +++                 _ASM_EXTABLE(2b, 3b)
+ + + + +  +++   +++                 : "=r" (*err), EAX_EDX_RET(val, low, high)
+++++ +++++++++++++++                : "c" (msr), "D" (0x9c5a203a), "i" (-EFAULT));
+ + + + +  +++   +++    return EAX_EDX_VAL(val, low, high);
+ + + + +  +++   +++ }
+ + + + +  +++   +++ 
                     static inline void native_write_msr(unsigned int msr,
                                                    unsigned low, unsigned high)
                     {
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge