Skip to content
  • Don Zickus's avatar
    perf/x86: Tweak broken BIOS rules during check_hw_exists() · 68ab7476
    Don Zickus authored and Ingo Molnar's avatar Ingo Molnar committed
    I stumbled upon an AMD box that had the BIOS using a hardware performance
    counter. Instead of printing out a warning and continuing, it failed and
    blocked further perf counter usage.
    
    Looking through the history, I found this commit:
    
      a5ebe0ba
    
     ("perf/x86: Check all MSRs before passing hw check")
    
    which tweaked the rules for a Xen guest on an almost identical box and now
    changed the behaviour.
    
    Unfortunately the rules were tweaked incorrectly and will always lead to
    MSR failures even though the MSRs are completely fine.
    
    What happens now is in arch/x86/kernel/cpu/perf_event.c::check_hw_exists():
    
    <snip>
            for (i = 0; i < x86_pmu.num_counters; i++) {
                    reg = x86_pmu_config_addr(i);
                    ret = rdmsrl_safe(reg, &val);
                    if (ret)
                            goto msr_fail;
                    if (val & ARCH_PERFMON_EVENTSEL_ENABLE) {
                            bios_fail = 1;
                            val_fail = val;
                            reg_fail = reg;
                    }
            }
    
    <snip>
            /*
             * Read the current value, change it and read it back to see if it
             * matches, this is needed to detect certain hardware emulators
             * (qemu/kvm) that don't trap on the MSR access and always return 0s.
             */
            reg = x86_pmu_event_addr(0);
    				^^^^
    
    if the first perf counter is enabled, then this routine will always fail
    because the counter is running. :-(
    
            if (rdmsrl_safe(reg, &val))
                    goto msr_fail;
            val ^= 0xffffUL;
            ret = wrmsrl_safe(reg, val);
            ret |= rdmsrl_safe(reg, &val_new);
            if (ret || val != val_new)
                    goto msr_fail;
    
    The above bios_fail used to be a 'goto' which is why it worked in the past.
    
    Further, most vendors have migrated to using fixed counters to hide their
    evilness hence this problem rarely shows up now days except on a few old boxes.
    
    I fixed my problem and kept the spirit of the original Xen fix, by recording a
    safe non-enable register to be used safely for the reading/writing check.
    Because it is not enabled, this passes on bare metal boxes (like metal), but
    should continue to throw an msr_fail on Xen guests because the register isn't
    emulated yet.
    
    Now I get a proper bios_fail error message and Xen should still see their
    msr_fail message (untested).
    
    Signed-off-by: default avatarDon Zickus <dzickus@redhat.com>
    Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
    Cc: Linus Torvalds <torvalds@linux-foundation.org>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Thomas Gleixner <tglx@linutronix.de>
    Cc: george.dunlap@eu.citrix.com
    Cc: konrad.wilk@oracle.com
    Link: http://lkml.kernel.org/r/1431976608-56970-1-git-send-email-dzickus@redhat.com
    
    
    Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
    68ab7476