linux/arch
Don Zickus 68ab747604 perf/x86: Tweak broken BIOS rules during check_hw_exists()
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:

  a5ebe0ba3d ("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: Don Zickus <dzickus@redhat.com>
Signed-off-by: Peter 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: Ingo Molnar <mingo@kernel.org>
2015-05-27 09:16:20 +02:00
..
alpha alpha: forward declare struct pt_regs in processor.h 2015-04-17 09:03:53 -04:00
arc ARC: inline cache flush toggle helpers 2015-05-11 11:21:41 +05:30
arm Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2015-05-22 15:44:50 -07:00
arm64 ARM: SoC fixes for 4.1-rc3 2015-05-16 15:33:25 -07:00
avr32 Merge branch 'exec_domain_rip_v2' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/misc 2015-04-15 13:53:55 -07:00
blackfin blackfin updates for Linux 4.1 2015-04-24 07:58:07 -07:00
c6x C6X Fixes for v4.1 2015-04-16 18:48:55 -04:00
cris CRIS changes for 4.1 2015-04-26 13:31:05 -07:00
frv Devicetree updates for 4.1: 2015-04-24 08:46:18 -07:00
hexagon Merge branch 'exec_domain_rip_v2' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/misc 2015-04-15 13:53:55 -07:00
ia64 Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2015-04-26 17:22:07 -07:00
m32r m32r: make flush_cpumask non-volatile. 2015-05-09 11:09:29 -07:00
m68k Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gerg/m68knommu 2015-04-20 10:12:29 -07:00
metag Metag architecture changes for v4.1 2015-04-24 07:56:50 -07:00
microblaze microblaze: use asm-generic for seccomp.h 2015-04-17 09:04:10 -04:00
mips MIPS: tlb-r4k: Fix PG_ELPA comment 2015-05-15 22:02:50 +02:00
mn10300 Devicetree updates for 4.1: 2015-04-24 08:46:18 -07:00
nios2 nios2 update for v4.1-rc1 2015-04-24 07:59:07 -07:00
openrisc Merge branch 'akpm' (patches from Andrew) 2015-04-15 16:39:15 -07:00
parisc parisc,metag: Fix crashes due to stack randomization on stack-grows-upwards architectures 2015-05-12 22:03:44 +02:00
powerpc This pull request includes a fix for two oopses, one on PPC 2015-05-21 20:15:16 -07:00
s390 Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6 2015-05-22 14:26:36 -07:00
score arch: Remove exec_domain from remaining archs 2015-04-12 21:03:30 +02:00
sh Merge branch 'for-linus' of git://git.infradead.org/users/vkoul/slave-dma 2015-04-24 09:49:37 -07:00
sparc Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc 2015-04-21 23:21:34 -07:00
tile tile: properly use node_isset() on a nodemask_t 2015-04-28 10:36:45 -04:00
um Merge branch 'exec_domain_rip_v2' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/misc 2015-04-15 13:53:55 -07:00
unicore32 Merge branch 'exec_domain_rip_v2' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/misc 2015-04-15 13:53:55 -07:00
x86 perf/x86: Tweak broken BIOS rules during check_hw_exists() 2015-05-27 09:16:20 +02:00
xtensa Xtensa changes and fixes for 4.1 2015-04-17 15:32:30 -04:00
.gitignore
Kconfig powerpc updates for 4.1 2015-04-16 13:53:32 -05:00