diff options
author | Ingo Molnar <mingo@kernel.org> | 2012-09-19 11:01:25 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2012-09-19 11:01:25 -0400 |
commit | f1f652447694f92beff8a534d94b36ea441c939a (patch) | |
tree | 177f029e418d517e39dfa2495a9a67a45381b833 /arch/x86/kernel/cpu | |
parent | 55babd8f41f122f5f4c7cebf520c766c983282c6 (diff) | |
parent | 5698bd757d55b1bb87edd1a9744ab09c142abfc2 (diff) |
Merge tag 'v3.6-rc6' into x86/mce
Merge Linux v3.6-rc6, to refresh this tree.
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/x86/kernel/cpu')
-rw-r--r-- | arch/x86/kernel/cpu/common.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce-severity.c | 7 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce.c | 43 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event.c | 89 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event.h | 20 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_amd_ibs.c | 4 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel.c | 11 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel_ds.c | 7 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel_lbr.c | 3 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel_uncore.c | 253 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel_uncore.h | 48 |
11 files changed, 317 insertions, 170 deletions
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 46d8786d655e..a5fbc3c5fccc 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
@@ -144,6 +144,8 @@ static int __init x86_xsave_setup(char *s) | |||
144 | { | 144 | { |
145 | setup_clear_cpu_cap(X86_FEATURE_XSAVE); | 145 | setup_clear_cpu_cap(X86_FEATURE_XSAVE); |
146 | setup_clear_cpu_cap(X86_FEATURE_XSAVEOPT); | 146 | setup_clear_cpu_cap(X86_FEATURE_XSAVEOPT); |
147 | setup_clear_cpu_cap(X86_FEATURE_AVX); | ||
148 | setup_clear_cpu_cap(X86_FEATURE_AVX2); | ||
147 | return 1; | 149 | return 1; |
148 | } | 150 | } |
149 | __setup("noxsave", x86_xsave_setup); | 151 | __setup("noxsave", x86_xsave_setup); |
diff --git a/arch/x86/kernel/cpu/mcheck/mce-severity.c b/arch/x86/kernel/cpu/mcheck/mce-severity.c index 413c2ced887c..13017626f9a8 100644 --- a/arch/x86/kernel/cpu/mcheck/mce-severity.c +++ b/arch/x86/kernel/cpu/mcheck/mce-severity.c | |||
@@ -55,13 +55,6 @@ static struct severity { | |||
55 | #define MCI_UC_S (MCI_STATUS_UC|MCI_STATUS_S) | 55 | #define MCI_UC_S (MCI_STATUS_UC|MCI_STATUS_S) |
56 | #define MCI_UC_SAR (MCI_STATUS_UC|MCI_STATUS_S|MCI_STATUS_AR) | 56 | #define MCI_UC_SAR (MCI_STATUS_UC|MCI_STATUS_S|MCI_STATUS_AR) |
57 | #define MCI_ADDR (MCI_STATUS_ADDRV|MCI_STATUS_MISCV) | 57 | #define MCI_ADDR (MCI_STATUS_ADDRV|MCI_STATUS_MISCV) |
58 | #define MCACOD 0xffff | ||
59 | /* Architecturally defined codes from SDM Vol. 3B Chapter 15 */ | ||
60 | #define MCACOD_SCRUB 0x00C0 /* 0xC0-0xCF Memory Scrubbing */ | ||
61 | #define MCACOD_SCRUBMSK 0xfff0 | ||
62 | #define MCACOD_L3WB 0x017A /* L3 Explicit Writeback */ | ||
63 | #define MCACOD_DATA 0x0134 /* Data Load */ | ||
64 | #define MCACOD_INSTR 0x0150 /* Instruction Fetch */ | ||
65 | 58 | ||
66 | MCESEV( | 59 | MCESEV( |
67 | NO, "Invalid", | 60 | NO, "Invalid", |
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 8c1beea6cabf..c311122ea838 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c | |||
@@ -103,6 +103,8 @@ DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = { | |||
103 | 103 | ||
104 | static DEFINE_PER_CPU(struct work_struct, mce_work); | 104 | static DEFINE_PER_CPU(struct work_struct, mce_work); |
105 | 105 | ||
106 | static void (*quirk_no_way_out)(int bank, struct mce *m, struct pt_regs *regs); | ||
107 | |||
106 | /* | 108 | /* |
107 | * CPU/chipset specific EDAC code can register a notifier call here to print | 109 | * CPU/chipset specific EDAC code can register a notifier call here to print |
108 | * MCE errors in a human-readable form. | 110 | * MCE errors in a human-readable form. |
@@ -650,14 +652,18 @@ EXPORT_SYMBOL_GPL(machine_check_poll); | |||
650 | * Do a quick check if any of the events requires a panic. | 652 | * Do a quick check if any of the events requires a panic. |
651 | * This decides if we keep the events around or clear them. | 653 | * This decides if we keep the events around or clear them. |
652 | */ | 654 | */ |
653 | static int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp) | 655 | static int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp, |
656 | struct pt_regs *regs) | ||
654 | { | 657 | { |
655 | int i, ret = 0; | 658 | int i, ret = 0; |
656 | 659 | ||
657 | for (i = 0; i < banks; i++) { | 660 | for (i = 0; i < banks; i++) { |
658 | m->status = mce_rdmsrl(MSR_IA32_MCx_STATUS(i)); | 661 | m->status = mce_rdmsrl(MSR_IA32_MCx_STATUS(i)); |
659 | if (m->status & MCI_STATUS_VAL) | 662 | if (m->status & MCI_STATUS_VAL) { |
660 | __set_bit(i, validp); | 663 | __set_bit(i, validp); |
664 | if (quirk_no_way_out) | ||
665 | quirk_no_way_out(i, m, regs); | ||
666 | } | ||
661 | if (mce_severity(m, tolerant, msg) >= MCE_PANIC_SEVERITY) | 667 | if (mce_severity(m, tolerant, msg) >= MCE_PANIC_SEVERITY) |
662 | ret = 1; | 668 | ret = 1; |
663 | } | 669 | } |
@@ -1040,7 +1046,7 @@ void do_machine_check(struct pt_regs *regs, long error_code) | |||
1040 | *final = m; | 1046 | *final = m; |
1041 | 1047 | ||
1042 | memset(valid_banks, 0, sizeof(valid_banks)); | 1048 | memset(valid_banks, 0, sizeof(valid_banks)); |
1043 | no_way_out = mce_no_way_out(&m, &msg, valid_banks); | 1049 | no_way_out = mce_no_way_out(&m, &msg, valid_banks, regs); |
1044 | 1050 | ||
1045 | barrier(); | 1051 | barrier(); |
1046 | 1052 | ||
@@ -1451,6 +1457,34 @@ static void __mcheck_cpu_init_generic(void) | |||
1451 | } | 1457 | } |
1452 | } | 1458 | } |
1453 | 1459 | ||
1460 | /* | ||
1461 | * During IFU recovery Sandy Bridge -EP4S processors set the RIPV and | ||
1462 | * EIPV bits in MCG_STATUS to zero on the affected logical processor (SDM | ||
1463 | * Vol 3B Table 15-20). But this confuses both the code that determines | ||
1464 | * whether the machine check occurred in kernel or user mode, and also | ||
1465 | * the severity assessment code. Pretend that EIPV was set, and take the | ||
1466 | * ip/cs values from the pt_regs that mce_gather_info() ignored earlier. | ||
1467 | */ | ||
1468 | static void quirk_sandybridge_ifu(int bank, struct mce *m, struct pt_regs *regs) | ||
1469 | { | ||
1470 | if (bank != 0) | ||
1471 | return; | ||
1472 | if ((m->mcgstatus & (MCG_STATUS_EIPV|MCG_STATUS_RIPV)) != 0) | ||
1473 | return; | ||
1474 | if ((m->status & (MCI_STATUS_OVER|MCI_STATUS_UC| | ||
1475 | MCI_STATUS_EN|MCI_STATUS_MISCV|MCI_STATUS_ADDRV| | ||
1476 | MCI_STATUS_PCC|MCI_STATUS_S|MCI_STATUS_AR| | ||
1477 | MCACOD)) != | ||
1478 | (MCI_STATUS_UC|MCI_STATUS_EN| | ||
1479 | MCI_STATUS_MISCV|MCI_STATUS_ADDRV|MCI_STATUS_S| | ||
1480 | MCI_STATUS_AR|MCACOD_INSTR)) | ||
1481 | return; | ||
1482 | |||
1483 | m->mcgstatus |= MCG_STATUS_EIPV; | ||
1484 | m->ip = regs->ip; | ||
1485 | m->cs = regs->cs; | ||
1486 | } | ||
1487 | |||
1454 | /* Add per CPU specific workarounds here */ | 1488 | /* Add per CPU specific workarounds here */ |
1455 | static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c) | 1489 | static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c) |
1456 | { | 1490 | { |
@@ -1548,6 +1582,9 @@ static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c) | |||
1548 | */ | 1582 | */ |
1549 | if (c->x86 == 6 && c->x86_model <= 13 && mce_bootlog < 0) | 1583 | if (c->x86 == 6 && c->x86_model <= 13 && mce_bootlog < 0) |
1550 | mce_bootlog = 0; | 1584 | mce_bootlog = 0; |
1585 | |||
1586 | if (c->x86 == 6 && c->x86_model == 45) | ||
1587 | quirk_no_way_out = quirk_sandybridge_ifu; | ||
1551 | } | 1588 | } |
1552 | if (monarch_timeout < 0) | 1589 | if (monarch_timeout < 0) |
1553 | monarch_timeout = 0; | 1590 | monarch_timeout = 0; |
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 29557aa06dda..915b876edd1e 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
@@ -32,6 +32,8 @@ | |||
32 | #include <asm/smp.h> | 32 | #include <asm/smp.h> |
33 | #include <asm/alternative.h> | 33 | #include <asm/alternative.h> |
34 | #include <asm/timer.h> | 34 | #include <asm/timer.h> |
35 | #include <asm/desc.h> | ||
36 | #include <asm/ldt.h> | ||
35 | 37 | ||
36 | #include "perf_event.h" | 38 | #include "perf_event.h" |
37 | 39 | ||
@@ -1738,6 +1740,29 @@ valid_user_frame(const void __user *fp, unsigned long size) | |||
1738 | return (__range_not_ok(fp, size, TASK_SIZE) == 0); | 1740 | return (__range_not_ok(fp, size, TASK_SIZE) == 0); |
1739 | } | 1741 | } |
1740 | 1742 | ||
1743 | static unsigned long get_segment_base(unsigned int segment) | ||
1744 | { | ||
1745 | struct desc_struct *desc; | ||
1746 | int idx = segment >> 3; | ||
1747 | |||
1748 | if ((segment & SEGMENT_TI_MASK) == SEGMENT_LDT) { | ||
1749 | if (idx > LDT_ENTRIES) | ||
1750 | return 0; | ||
1751 | |||
1752 | if (idx > current->active_mm->context.size) | ||
1753 | return 0; | ||
1754 | |||
1755 | desc = current->active_mm->context.ldt; | ||
1756 | } else { | ||
1757 | if (idx > GDT_ENTRIES) | ||
1758 | return 0; | ||
1759 | |||
1760 | desc = __this_cpu_ptr(&gdt_page.gdt[0]); | ||
1761 | } | ||
1762 | |||
1763 | return get_desc_base(desc + idx); | ||
1764 | } | ||
1765 | |||
1741 | #ifdef CONFIG_COMPAT | 1766 | #ifdef CONFIG_COMPAT |
1742 | 1767 | ||
1743 | #include <asm/compat.h> | 1768 | #include <asm/compat.h> |
@@ -1746,13 +1771,17 @@ static inline int | |||
1746 | perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry) | 1771 | perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry) |
1747 | { | 1772 | { |
1748 | /* 32-bit process in 64-bit kernel. */ | 1773 | /* 32-bit process in 64-bit kernel. */ |
1774 | unsigned long ss_base, cs_base; | ||
1749 | struct stack_frame_ia32 frame; | 1775 | struct stack_frame_ia32 frame; |
1750 | const void __user *fp; | 1776 | const void __user *fp; |
1751 | 1777 | ||
1752 | if (!test_thread_flag(TIF_IA32)) | 1778 | if (!test_thread_flag(TIF_IA32)) |
1753 | return 0; | 1779 | return 0; |
1754 | 1780 | ||
1755 | fp = compat_ptr(regs->bp); | 1781 | cs_base = get_segment_base(regs->cs); |
1782 | ss_base = get_segment_base(regs->ss); | ||
1783 | |||
1784 | fp = compat_ptr(ss_base + regs->bp); | ||
1756 | while (entry->nr < PERF_MAX_STACK_DEPTH) { | 1785 | while (entry->nr < PERF_MAX_STACK_DEPTH) { |
1757 | unsigned long bytes; | 1786 | unsigned long bytes; |
1758 | frame.next_frame = 0; | 1787 | frame.next_frame = 0; |
@@ -1765,8 +1794,8 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry) | |||
1765 | if (!valid_user_frame(fp, sizeof(frame))) | 1794 | if (!valid_user_frame(fp, sizeof(frame))) |
1766 | break; | 1795 | break; |
1767 | 1796 | ||
1768 | perf_callchain_store(entry, frame.return_address); | 1797 | perf_callchain_store(entry, cs_base + frame.return_address); |
1769 | fp = compat_ptr(frame.next_frame); | 1798 | fp = compat_ptr(ss_base + frame.next_frame); |
1770 | } | 1799 | } |
1771 | return 1; | 1800 | return 1; |
1772 | } | 1801 | } |
@@ -1789,6 +1818,12 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) | |||
1789 | return; | 1818 | return; |
1790 | } | 1819 | } |
1791 | 1820 | ||
1821 | /* | ||
1822 | * We don't know what to do with VM86 stacks.. ignore them for now. | ||
1823 | */ | ||
1824 | if (regs->flags & (X86_VM_MASK | PERF_EFLAGS_VM)) | ||
1825 | return; | ||
1826 | |||
1792 | fp = (void __user *)regs->bp; | 1827 | fp = (void __user *)regs->bp; |
1793 | 1828 | ||
1794 | perf_callchain_store(entry, regs->ip); | 1829 | perf_callchain_store(entry, regs->ip); |
@@ -1816,16 +1851,50 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) | |||
1816 | } | 1851 | } |
1817 | } | 1852 | } |
1818 | 1853 | ||
1819 | unsigned long perf_instruction_pointer(struct pt_regs *regs) | 1854 | /* |
1855 | * Deal with code segment offsets for the various execution modes: | ||
1856 | * | ||
1857 | * VM86 - the good olde 16 bit days, where the linear address is | ||
1858 | * 20 bits and we use regs->ip + 0x10 * regs->cs. | ||
1859 | * | ||
1860 | * IA32 - Where we need to look at GDT/LDT segment descriptor tables | ||
1861 | * to figure out what the 32bit base address is. | ||
1862 | * | ||
1863 | * X32 - has TIF_X32 set, but is running in x86_64 | ||
1864 | * | ||
1865 | * X86_64 - CS,DS,SS,ES are all zero based. | ||
1866 | */ | ||
1867 | static unsigned long code_segment_base(struct pt_regs *regs) | ||
1820 | { | 1868 | { |
1821 | unsigned long ip; | 1869 | /* |
1870 | * If we are in VM86 mode, add the segment offset to convert to a | ||
1871 | * linear address. | ||
1872 | */ | ||
1873 | if (regs->flags & X86_VM_MASK) | ||
1874 | return 0x10 * regs->cs; | ||
1875 | |||
1876 | /* | ||
1877 | * For IA32 we look at the GDT/LDT segment base to convert the | ||
1878 | * effective IP to a linear address. | ||
1879 | */ | ||
1880 | #ifdef CONFIG_X86_32 | ||
1881 | if (user_mode(regs) && regs->cs != __USER_CS) | ||
1882 | return get_segment_base(regs->cs); | ||
1883 | #else | ||
1884 | if (test_thread_flag(TIF_IA32)) { | ||
1885 | if (user_mode(regs) && regs->cs != __USER32_CS) | ||
1886 | return get_segment_base(regs->cs); | ||
1887 | } | ||
1888 | #endif | ||
1889 | return 0; | ||
1890 | } | ||
1822 | 1891 | ||
1892 | unsigned long perf_instruction_pointer(struct pt_regs *regs) | ||
1893 | { | ||
1823 | if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) | 1894 | if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) |
1824 | ip = perf_guest_cbs->get_guest_ip(); | 1895 | return perf_guest_cbs->get_guest_ip(); |
1825 | else | ||
1826 | ip = instruction_pointer(regs); | ||
1827 | 1896 | ||
1828 | return ip; | 1897 | return regs->ip + code_segment_base(regs); |
1829 | } | 1898 | } |
1830 | 1899 | ||
1831 | unsigned long perf_misc_flags(struct pt_regs *regs) | 1900 | unsigned long perf_misc_flags(struct pt_regs *regs) |
@@ -1838,7 +1907,7 @@ unsigned long perf_misc_flags(struct pt_regs *regs) | |||
1838 | else | 1907 | else |
1839 | misc |= PERF_RECORD_MISC_GUEST_KERNEL; | 1908 | misc |= PERF_RECORD_MISC_GUEST_KERNEL; |
1840 | } else { | 1909 | } else { |
1841 | if (!kernel_ip(regs->ip)) | 1910 | if (user_mode(regs)) |
1842 | misc |= PERF_RECORD_MISC_USER; | 1911 | misc |= PERF_RECORD_MISC_USER; |
1843 | else | 1912 | else |
1844 | misc |= PERF_RECORD_MISC_KERNEL; | 1913 | misc |= PERF_RECORD_MISC_KERNEL; |
diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h index 821d53b696d1..6605a81ba339 100644 --- a/arch/x86/kernel/cpu/perf_event.h +++ b/arch/x86/kernel/cpu/perf_event.h | |||
@@ -516,6 +516,26 @@ static inline bool kernel_ip(unsigned long ip) | |||
516 | #endif | 516 | #endif |
517 | } | 517 | } |
518 | 518 | ||
519 | /* | ||
520 | * Not all PMUs provide the right context information to place the reported IP | ||
521 | * into full context. Specifically segment registers are typically not | ||
522 | * supplied. | ||
523 | * | ||
524 | * Assuming the address is a linear address (it is for IBS), we fake the CS and | ||
525 | * vm86 mode using the known zero-based code segment and 'fix up' the registers | ||
526 | * to reflect this. | ||
527 | * | ||
528 | * Intel PEBS/LBR appear to typically provide the effective address, nothing | ||
529 | * much we can do about that but pray and treat it like a linear address. | ||
530 | */ | ||
531 | static inline void set_linear_ip(struct pt_regs *regs, unsigned long ip) | ||
532 | { | ||
533 | regs->cs = kernel_ip(ip) ? __KERNEL_CS : __USER_CS; | ||
534 | if (regs->flags & X86_VM_MASK) | ||
535 | regs->flags ^= (PERF_EFLAGS_VM | X86_VM_MASK); | ||
536 | regs->ip = ip; | ||
537 | } | ||
538 | |||
519 | #ifdef CONFIG_CPU_SUP_AMD | 539 | #ifdef CONFIG_CPU_SUP_AMD |
520 | 540 | ||
521 | int amd_pmu_init(void); | 541 | int amd_pmu_init(void); |
diff --git a/arch/x86/kernel/cpu/perf_event_amd_ibs.c b/arch/x86/kernel/cpu/perf_event_amd_ibs.c index da9bcdcd9856..7bfb5bec8630 100644 --- a/arch/x86/kernel/cpu/perf_event_amd_ibs.c +++ b/arch/x86/kernel/cpu/perf_event_amd_ibs.c | |||
@@ -13,6 +13,8 @@ | |||
13 | 13 | ||
14 | #include <asm/apic.h> | 14 | #include <asm/apic.h> |
15 | 15 | ||
16 | #include "perf_event.h" | ||
17 | |||
16 | static u32 ibs_caps; | 18 | static u32 ibs_caps; |
17 | 19 | ||
18 | #if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_AMD) | 20 | #if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_AMD) |
@@ -536,7 +538,7 @@ static int perf_ibs_handle_irq(struct perf_ibs *perf_ibs, struct pt_regs *iregs) | |||
536 | if (check_rip && (ibs_data.regs[2] & IBS_RIP_INVALID)) { | 538 | if (check_rip && (ibs_data.regs[2] & IBS_RIP_INVALID)) { |
537 | regs.flags &= ~PERF_EFLAGS_EXACT; | 539 | regs.flags &= ~PERF_EFLAGS_EXACT; |
538 | } else { | 540 | } else { |
539 | instruction_pointer_set(®s, ibs_data.regs[1]); | 541 | set_linear_ip(®s, ibs_data.regs[1]); |
540 | regs.flags |= PERF_EFLAGS_EXACT; | 542 | regs.flags |= PERF_EFLAGS_EXACT; |
541 | } | 543 | } |
542 | 544 | ||
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 382366977d4c..0d3d63afa76a 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c | |||
@@ -1522,8 +1522,16 @@ static struct perf_guest_switch_msr *intel_guest_get_msrs(int *nr) | |||
1522 | arr[0].msr = MSR_CORE_PERF_GLOBAL_CTRL; | 1522 | arr[0].msr = MSR_CORE_PERF_GLOBAL_CTRL; |
1523 | arr[0].host = x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_guest_mask; | 1523 | arr[0].host = x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_guest_mask; |
1524 | arr[0].guest = x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_host_mask; | 1524 | arr[0].guest = x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_host_mask; |
1525 | /* | ||
1526 | * If PMU counter has PEBS enabled it is not enough to disable counter | ||
1527 | * on a guest entry since PEBS memory write can overshoot guest entry | ||
1528 | * and corrupt guest memory. Disabling PEBS solves the problem. | ||
1529 | */ | ||
1530 | arr[1].msr = MSR_IA32_PEBS_ENABLE; | ||
1531 | arr[1].host = cpuc->pebs_enabled; | ||
1532 | arr[1].guest = 0; | ||
1525 | 1533 | ||
1526 | *nr = 1; | 1534 | *nr = 2; |
1527 | return arr; | 1535 | return arr; |
1528 | } | 1536 | } |
1529 | 1537 | ||
@@ -2000,6 +2008,7 @@ __init int intel_pmu_init(void) | |||
2000 | break; | 2008 | break; |
2001 | 2009 | ||
2002 | case 28: /* Atom */ | 2010 | case 28: /* Atom */ |
2011 | case 54: /* Cedariew */ | ||
2003 | memcpy(hw_cache_event_ids, atom_hw_cache_event_ids, | 2012 | memcpy(hw_cache_event_ids, atom_hw_cache_event_ids, |
2004 | sizeof(hw_cache_event_ids)); | 2013 | sizeof(hw_cache_event_ids)); |
2005 | 2014 | ||
diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index 629ae0b7ad90..e38d97bf4259 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c | |||
@@ -499,7 +499,7 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs) | |||
499 | * We sampled a branch insn, rewind using the LBR stack | 499 | * We sampled a branch insn, rewind using the LBR stack |
500 | */ | 500 | */ |
501 | if (ip == to) { | 501 | if (ip == to) { |
502 | regs->ip = from; | 502 | set_linear_ip(regs, from); |
503 | return 1; | 503 | return 1; |
504 | } | 504 | } |
505 | 505 | ||
@@ -529,7 +529,7 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs) | |||
529 | } while (to < ip); | 529 | } while (to < ip); |
530 | 530 | ||
531 | if (to == ip) { | 531 | if (to == ip) { |
532 | regs->ip = old_to; | 532 | set_linear_ip(regs, old_to); |
533 | return 1; | 533 | return 1; |
534 | } | 534 | } |
535 | 535 | ||
@@ -569,7 +569,8 @@ static void __intel_pmu_pebs_event(struct perf_event *event, | |||
569 | * A possible PERF_SAMPLE_REGS will have to transfer all regs. | 569 | * A possible PERF_SAMPLE_REGS will have to transfer all regs. |
570 | */ | 570 | */ |
571 | regs = *iregs; | 571 | regs = *iregs; |
572 | regs.ip = pebs->ip; | 572 | regs.flags = pebs->flags; |
573 | set_linear_ip(®s, pebs->ip); | ||
573 | regs.bp = pebs->bp; | 574 | regs.bp = pebs->bp; |
574 | regs.sp = pebs->sp; | 575 | regs.sp = pebs->sp; |
575 | 576 | ||
diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/arch/x86/kernel/cpu/perf_event_intel_lbr.c index 520b4265fcd2..da02e9cc3754 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_lbr.c +++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c | |||
@@ -686,7 +686,8 @@ void intel_pmu_lbr_init_atom(void) | |||
686 | * to have an operational LBR which can freeze | 686 | * to have an operational LBR which can freeze |
687 | * on PMU interrupt | 687 | * on PMU interrupt |
688 | */ | 688 | */ |
689 | if (boot_cpu_data.x86_mask < 10) { | 689 | if (boot_cpu_data.x86_model == 28 |
690 | && boot_cpu_data.x86_mask < 10) { | ||
690 | pr_cont("LBR disabled due to erratum"); | 691 | pr_cont("LBR disabled due to erratum"); |
691 | return; | 692 | return; |
692 | } | 693 | } |
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c index 7563fda9f033..0a5571080e74 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c | |||
@@ -796,7 +796,6 @@ static struct intel_uncore_type *nhm_msr_uncores[] = { | |||
796 | 796 | ||
797 | DEFINE_UNCORE_FORMAT_ATTR(event5, event, "config:1-5"); | 797 | DEFINE_UNCORE_FORMAT_ATTR(event5, event, "config:1-5"); |
798 | DEFINE_UNCORE_FORMAT_ATTR(counter, counter, "config:6-7"); | 798 | DEFINE_UNCORE_FORMAT_ATTR(counter, counter, "config:6-7"); |
799 | DEFINE_UNCORE_FORMAT_ATTR(mm_cfg, mm_cfg, "config:63"); | ||
800 | DEFINE_UNCORE_FORMAT_ATTR(match, match, "config1:0-63"); | 799 | DEFINE_UNCORE_FORMAT_ATTR(match, match, "config1:0-63"); |
801 | DEFINE_UNCORE_FORMAT_ATTR(mask, mask, "config2:0-63"); | 800 | DEFINE_UNCORE_FORMAT_ATTR(mask, mask, "config2:0-63"); |
802 | 801 | ||
@@ -902,16 +901,21 @@ static struct attribute_group nhmex_uncore_cbox_format_group = { | |||
902 | .attrs = nhmex_uncore_cbox_formats_attr, | 901 | .attrs = nhmex_uncore_cbox_formats_attr, |
903 | }; | 902 | }; |
904 | 903 | ||
904 | /* msr offset for each instance of cbox */ | ||
905 | static unsigned nhmex_cbox_msr_offsets[] = { | ||
906 | 0x0, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x240, 0x2c0, | ||
907 | }; | ||
908 | |||
905 | static struct intel_uncore_type nhmex_uncore_cbox = { | 909 | static struct intel_uncore_type nhmex_uncore_cbox = { |
906 | .name = "cbox", | 910 | .name = "cbox", |
907 | .num_counters = 6, | 911 | .num_counters = 6, |
908 | .num_boxes = 8, | 912 | .num_boxes = 10, |
909 | .perf_ctr_bits = 48, | 913 | .perf_ctr_bits = 48, |
910 | .event_ctl = NHMEX_C0_MSR_PMON_EV_SEL0, | 914 | .event_ctl = NHMEX_C0_MSR_PMON_EV_SEL0, |
911 | .perf_ctr = NHMEX_C0_MSR_PMON_CTR0, | 915 | .perf_ctr = NHMEX_C0_MSR_PMON_CTR0, |
912 | .event_mask = NHMEX_PMON_RAW_EVENT_MASK, | 916 | .event_mask = NHMEX_PMON_RAW_EVENT_MASK, |
913 | .box_ctl = NHMEX_C0_MSR_PMON_GLOBAL_CTL, | 917 | .box_ctl = NHMEX_C0_MSR_PMON_GLOBAL_CTL, |
914 | .msr_offset = NHMEX_C_MSR_OFFSET, | 918 | .msr_offsets = nhmex_cbox_msr_offsets, |
915 | .pair_ctr_ctl = 1, | 919 | .pair_ctr_ctl = 1, |
916 | .ops = &nhmex_uncore_ops, | 920 | .ops = &nhmex_uncore_ops, |
917 | .format_group = &nhmex_uncore_cbox_format_group | 921 | .format_group = &nhmex_uncore_cbox_format_group |
@@ -1032,24 +1036,22 @@ static struct intel_uncore_type nhmex_uncore_bbox = { | |||
1032 | 1036 | ||
1033 | static int nhmex_sbox_hw_config(struct intel_uncore_box *box, struct perf_event *event) | 1037 | static int nhmex_sbox_hw_config(struct intel_uncore_box *box, struct perf_event *event) |
1034 | { | 1038 | { |
1035 | struct hw_perf_event_extra *reg1 = &event->hw.extra_reg; | 1039 | struct hw_perf_event *hwc = &event->hw; |
1036 | struct hw_perf_event_extra *reg2 = &event->hw.branch_reg; | 1040 | struct hw_perf_event_extra *reg1 = &hwc->extra_reg; |
1041 | struct hw_perf_event_extra *reg2 = &hwc->branch_reg; | ||
1037 | 1042 | ||
1038 | if (event->attr.config & NHMEX_S_PMON_MM_CFG_EN) { | 1043 | /* only TO_R_PROG_EV event uses the match/mask register */ |
1039 | reg1->config = event->attr.config1; | 1044 | if ((hwc->config & NHMEX_PMON_CTL_EV_SEL_MASK) != |
1040 | reg2->config = event->attr.config2; | 1045 | NHMEX_S_EVENT_TO_R_PROG_EV) |
1041 | } else { | 1046 | return 0; |
1042 | reg1->config = ~0ULL; | ||
1043 | reg2->config = ~0ULL; | ||
1044 | } | ||
1045 | 1047 | ||
1046 | if (box->pmu->pmu_idx == 0) | 1048 | if (box->pmu->pmu_idx == 0) |
1047 | reg1->reg = NHMEX_S0_MSR_MM_CFG; | 1049 | reg1->reg = NHMEX_S0_MSR_MM_CFG; |
1048 | else | 1050 | else |
1049 | reg1->reg = NHMEX_S1_MSR_MM_CFG; | 1051 | reg1->reg = NHMEX_S1_MSR_MM_CFG; |
1050 | |||
1051 | reg1->idx = 0; | 1052 | reg1->idx = 0; |
1052 | 1053 | reg1->config = event->attr.config1; | |
1054 | reg2->config = event->attr.config2; | ||
1053 | return 0; | 1055 | return 0; |
1054 | } | 1056 | } |
1055 | 1057 | ||
@@ -1059,8 +1061,8 @@ static void nhmex_sbox_msr_enable_event(struct intel_uncore_box *box, struct per | |||
1059 | struct hw_perf_event_extra *reg1 = &hwc->extra_reg; | 1061 | struct hw_perf_event_extra *reg1 = &hwc->extra_reg; |
1060 | struct hw_perf_event_extra *reg2 = &hwc->branch_reg; | 1062 | struct hw_perf_event_extra *reg2 = &hwc->branch_reg; |
1061 | 1063 | ||
1062 | wrmsrl(reg1->reg, 0); | 1064 | if (reg1->idx != EXTRA_REG_NONE) { |
1063 | if (reg1->config != ~0ULL || reg2->config != ~0ULL) { | 1065 | wrmsrl(reg1->reg, 0); |
1064 | wrmsrl(reg1->reg + 1, reg1->config); | 1066 | wrmsrl(reg1->reg + 1, reg1->config); |
1065 | wrmsrl(reg1->reg + 2, reg2->config); | 1067 | wrmsrl(reg1->reg + 2, reg2->config); |
1066 | wrmsrl(reg1->reg, NHMEX_S_PMON_MM_CFG_EN); | 1068 | wrmsrl(reg1->reg, NHMEX_S_PMON_MM_CFG_EN); |
@@ -1074,7 +1076,6 @@ static struct attribute *nhmex_uncore_sbox_formats_attr[] = { | |||
1074 | &format_attr_edge.attr, | 1076 | &format_attr_edge.attr, |
1075 | &format_attr_inv.attr, | 1077 | &format_attr_inv.attr, |
1076 | &format_attr_thresh8.attr, | 1078 | &format_attr_thresh8.attr, |
1077 | &format_attr_mm_cfg.attr, | ||
1078 | &format_attr_match.attr, | 1079 | &format_attr_match.attr, |
1079 | &format_attr_mask.attr, | 1080 | &format_attr_mask.attr, |
1080 | NULL, | 1081 | NULL, |
@@ -1142,6 +1143,9 @@ static struct extra_reg nhmex_uncore_mbox_extra_regs[] = { | |||
1142 | EVENT_EXTRA_END | 1143 | EVENT_EXTRA_END |
1143 | }; | 1144 | }; |
1144 | 1145 | ||
1146 | /* Nehalem-EX or Westmere-EX ? */ | ||
1147 | bool uncore_nhmex; | ||
1148 | |||
1145 | static bool nhmex_mbox_get_shared_reg(struct intel_uncore_box *box, int idx, u64 config) | 1149 | static bool nhmex_mbox_get_shared_reg(struct intel_uncore_box *box, int idx, u64 config) |
1146 | { | 1150 | { |
1147 | struct intel_uncore_extra_reg *er; | 1151 | struct intel_uncore_extra_reg *er; |
@@ -1171,18 +1175,29 @@ static bool nhmex_mbox_get_shared_reg(struct intel_uncore_box *box, int idx, u64 | |||
1171 | return false; | 1175 | return false; |
1172 | 1176 | ||
1173 | /* mask of the shared fields */ | 1177 | /* mask of the shared fields */ |
1174 | mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK; | 1178 | if (uncore_nhmex) |
1179 | mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK; | ||
1180 | else | ||
1181 | mask = WSMEX_M_PMON_ZDP_CTL_FVC_MASK; | ||
1175 | er = &box->shared_regs[EXTRA_REG_NHMEX_M_ZDP_CTL_FVC]; | 1182 | er = &box->shared_regs[EXTRA_REG_NHMEX_M_ZDP_CTL_FVC]; |
1176 | 1183 | ||
1177 | raw_spin_lock_irqsave(&er->lock, flags); | 1184 | raw_spin_lock_irqsave(&er->lock, flags); |
1178 | /* add mask of the non-shared field if it's in use */ | 1185 | /* add mask of the non-shared field if it's in use */ |
1179 | if (__BITS_VALUE(atomic_read(&er->ref), idx, 8)) | 1186 | if (__BITS_VALUE(atomic_read(&er->ref), idx, 8)) { |
1180 | mask |= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); | 1187 | if (uncore_nhmex) |
1188 | mask |= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); | ||
1189 | else | ||
1190 | mask |= WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); | ||
1191 | } | ||
1181 | 1192 | ||
1182 | if (!atomic_read(&er->ref) || !((er->config ^ config) & mask)) { | 1193 | if (!atomic_read(&er->ref) || !((er->config ^ config) & mask)) { |
1183 | atomic_add(1 << (idx * 8), &er->ref); | 1194 | atomic_add(1 << (idx * 8), &er->ref); |
1184 | mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK | | 1195 | if (uncore_nhmex) |
1185 | NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); | 1196 | mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK | |
1197 | NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); | ||
1198 | else | ||
1199 | mask = WSMEX_M_PMON_ZDP_CTL_FVC_MASK | | ||
1200 | WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); | ||
1186 | er->config &= ~mask; | 1201 | er->config &= ~mask; |
1187 | er->config |= (config & mask); | 1202 | er->config |= (config & mask); |
1188 | ret = true; | 1203 | ret = true; |
@@ -1216,7 +1231,10 @@ u64 nhmex_mbox_alter_er(struct perf_event *event, int new_idx, bool modify) | |||
1216 | 1231 | ||
1217 | /* get the non-shared control bits and shift them */ | 1232 | /* get the non-shared control bits and shift them */ |
1218 | idx = orig_idx - EXTRA_REG_NHMEX_M_ZDP_CTL_FVC; | 1233 | idx = orig_idx - EXTRA_REG_NHMEX_M_ZDP_CTL_FVC; |
1219 | config &= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); | 1234 | if (uncore_nhmex) |
1235 | config &= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); | ||
1236 | else | ||
1237 | config &= WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); | ||
1220 | if (new_idx > orig_idx) { | 1238 | if (new_idx > orig_idx) { |
1221 | idx = new_idx - orig_idx; | 1239 | idx = new_idx - orig_idx; |
1222 | config <<= 3 * idx; | 1240 | config <<= 3 * idx; |
@@ -1226,6 +1244,10 @@ u64 nhmex_mbox_alter_er(struct perf_event *event, int new_idx, bool modify) | |||
1226 | } | 1244 | } |
1227 | 1245 | ||
1228 | /* add the shared control bits back */ | 1246 | /* add the shared control bits back */ |
1247 | if (uncore_nhmex) | ||
1248 | config |= NHMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config; | ||
1249 | else | ||
1250 | config |= WSMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config; | ||
1229 | config |= NHMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config; | 1251 | config |= NHMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config; |
1230 | if (modify) { | 1252 | if (modify) { |
1231 | /* adjust the main event selector */ | 1253 | /* adjust the main event selector */ |
@@ -1264,7 +1286,8 @@ again: | |||
1264 | } | 1286 | } |
1265 | 1287 | ||
1266 | /* for the match/mask registers */ | 1288 | /* for the match/mask registers */ |
1267 | if ((uncore_box_is_fake(box) || !reg2->alloc) && | 1289 | if (reg2->idx != EXTRA_REG_NONE && |
1290 | (uncore_box_is_fake(box) || !reg2->alloc) && | ||
1268 | !nhmex_mbox_get_shared_reg(box, reg2->idx, reg2->config)) | 1291 | !nhmex_mbox_get_shared_reg(box, reg2->idx, reg2->config)) |
1269 | goto fail; | 1292 | goto fail; |
1270 | 1293 | ||
@@ -1278,7 +1301,8 @@ again: | |||
1278 | if (idx[0] != 0xff && idx[0] != __BITS_VALUE(reg1->idx, 0, 8)) | 1301 | if (idx[0] != 0xff && idx[0] != __BITS_VALUE(reg1->idx, 0, 8)) |
1279 | nhmex_mbox_alter_er(event, idx[0], true); | 1302 | nhmex_mbox_alter_er(event, idx[0], true); |
1280 | reg1->alloc |= alloc; | 1303 | reg1->alloc |= alloc; |
1281 | reg2->alloc = 1; | 1304 | if (reg2->idx != EXTRA_REG_NONE) |
1305 | reg2->alloc = 1; | ||
1282 | } | 1306 | } |
1283 | return NULL; | 1307 | return NULL; |
1284 | fail: | 1308 | fail: |
@@ -1342,9 +1366,6 @@ static int nhmex_mbox_hw_config(struct intel_uncore_box *box, struct perf_event | |||
1342 | struct extra_reg *er; | 1366 | struct extra_reg *er; |
1343 | unsigned msr; | 1367 | unsigned msr; |
1344 | int reg_idx = 0; | 1368 | int reg_idx = 0; |
1345 | |||
1346 | if (WARN_ON_ONCE(reg1->idx != -1)) | ||
1347 | return -EINVAL; | ||
1348 | /* | 1369 | /* |
1349 | * The mbox events may require 2 extra MSRs at the most. But only | 1370 | * The mbox events may require 2 extra MSRs at the most. But only |
1350 | * the lower 32 bits in these MSRs are significant, so we can use | 1371 | * the lower 32 bits in these MSRs are significant, so we can use |
@@ -1355,11 +1376,6 @@ static int nhmex_mbox_hw_config(struct intel_uncore_box *box, struct perf_event | |||
1355 | continue; | 1376 | continue; |
1356 | if (event->attr.config1 & ~er->valid_mask) | 1377 | if (event->attr.config1 & ~er->valid_mask) |
1357 | return -EINVAL; | 1378 | return -EINVAL; |
1358 | if (er->idx == __BITS_VALUE(reg1->idx, 0, 8) || | ||
1359 | er->idx == __BITS_VALUE(reg1->idx, 1, 8)) | ||
1360 | continue; | ||
1361 | if (WARN_ON_ONCE(reg_idx >= 2)) | ||
1362 | return -EINVAL; | ||
1363 | 1379 | ||
1364 | msr = er->msr + type->msr_offset * box->pmu->pmu_idx; | 1380 | msr = er->msr + type->msr_offset * box->pmu->pmu_idx; |
1365 | if (WARN_ON_ONCE(msr >= 0xffff || er->idx >= 0xff)) | 1381 | if (WARN_ON_ONCE(msr >= 0xffff || er->idx >= 0xff)) |
@@ -1368,6 +1384,8 @@ static int nhmex_mbox_hw_config(struct intel_uncore_box *box, struct perf_event | |||
1368 | /* always use the 32~63 bits to pass the PLD config */ | 1384 | /* always use the 32~63 bits to pass the PLD config */ |
1369 | if (er->idx == EXTRA_REG_NHMEX_M_PLD) | 1385 | if (er->idx == EXTRA_REG_NHMEX_M_PLD) |
1370 | reg_idx = 1; | 1386 | reg_idx = 1; |
1387 | else if (WARN_ON_ONCE(reg_idx > 0)) | ||
1388 | return -EINVAL; | ||
1371 | 1389 | ||
1372 | reg1->idx &= ~(0xff << (reg_idx * 8)); | 1390 | reg1->idx &= ~(0xff << (reg_idx * 8)); |
1373 | reg1->reg &= ~(0xffff << (reg_idx * 16)); | 1391 | reg1->reg &= ~(0xffff << (reg_idx * 16)); |
@@ -1376,17 +1394,21 @@ static int nhmex_mbox_hw_config(struct intel_uncore_box *box, struct perf_event | |||
1376 | reg1->config = event->attr.config1; | 1394 | reg1->config = event->attr.config1; |
1377 | reg_idx++; | 1395 | reg_idx++; |
1378 | } | 1396 | } |
1379 | /* use config2 to pass the filter config */ | 1397 | /* |
1380 | reg2->idx = EXTRA_REG_NHMEX_M_FILTER; | 1398 | * The mbox only provides ability to perform address matching |
1381 | if (event->attr.config2 & NHMEX_M_PMON_MM_CFG_EN) | 1399 | * for the PLD events. |
1382 | reg2->config = event->attr.config2; | 1400 | */ |
1383 | else | 1401 | if (reg_idx == 2) { |
1384 | reg2->config = ~0ULL; | 1402 | reg2->idx = EXTRA_REG_NHMEX_M_FILTER; |
1385 | if (box->pmu->pmu_idx == 0) | 1403 | if (event->attr.config2 & NHMEX_M_PMON_MM_CFG_EN) |
1386 | reg2->reg = NHMEX_M0_MSR_PMU_MM_CFG; | 1404 | reg2->config = event->attr.config2; |
1387 | else | 1405 | else |
1388 | reg2->reg = NHMEX_M1_MSR_PMU_MM_CFG; | 1406 | reg2->config = ~0ULL; |
1389 | 1407 | if (box->pmu->pmu_idx == 0) | |
1408 | reg2->reg = NHMEX_M0_MSR_PMU_MM_CFG; | ||
1409 | else | ||
1410 | reg2->reg = NHMEX_M1_MSR_PMU_MM_CFG; | ||
1411 | } | ||
1390 | return 0; | 1412 | return 0; |
1391 | } | 1413 | } |
1392 | 1414 | ||
@@ -1422,34 +1444,36 @@ static void nhmex_mbox_msr_enable_event(struct intel_uncore_box *box, struct per | |||
1422 | wrmsrl(__BITS_VALUE(reg1->reg, 1, 16), | 1444 | wrmsrl(__BITS_VALUE(reg1->reg, 1, 16), |
1423 | nhmex_mbox_shared_reg_config(box, idx)); | 1445 | nhmex_mbox_shared_reg_config(box, idx)); |
1424 | 1446 | ||
1425 | wrmsrl(reg2->reg, 0); | 1447 | if (reg2->idx != EXTRA_REG_NONE) { |
1426 | if (reg2->config != ~0ULL) { | 1448 | wrmsrl(reg2->reg, 0); |
1427 | wrmsrl(reg2->reg + 1, | 1449 | if (reg2->config != ~0ULL) { |
1428 | reg2->config & NHMEX_M_PMON_ADDR_MATCH_MASK); | 1450 | wrmsrl(reg2->reg + 1, |
1429 | wrmsrl(reg2->reg + 2, NHMEX_M_PMON_ADDR_MASK_MASK & | 1451 | reg2->config & NHMEX_M_PMON_ADDR_MATCH_MASK); |
1430 | (reg2->config >> NHMEX_M_PMON_ADDR_MASK_SHIFT)); | 1452 | wrmsrl(reg2->reg + 2, NHMEX_M_PMON_ADDR_MASK_MASK & |
1431 | wrmsrl(reg2->reg, NHMEX_M_PMON_MM_CFG_EN); | 1453 | (reg2->config >> NHMEX_M_PMON_ADDR_MASK_SHIFT)); |
1454 | wrmsrl(reg2->reg, NHMEX_M_PMON_MM_CFG_EN); | ||
1455 | } | ||
1432 | } | 1456 | } |
1433 | 1457 | ||
1434 | wrmsrl(hwc->config_base, hwc->config | NHMEX_PMON_CTL_EN_BIT0); | 1458 | wrmsrl(hwc->config_base, hwc->config | NHMEX_PMON_CTL_EN_BIT0); |
1435 | } | 1459 | } |
1436 | 1460 | ||
1437 | DEFINE_UNCORE_FORMAT_ATTR(count_mode, count_mode, "config:2-3"); | 1461 | DEFINE_UNCORE_FORMAT_ATTR(count_mode, count_mode, "config:2-3"); |
1438 | DEFINE_UNCORE_FORMAT_ATTR(storage_mode, storage_mode, "config:4-5"); | 1462 | DEFINE_UNCORE_FORMAT_ATTR(storage_mode, storage_mode, "config:4-5"); |
1439 | DEFINE_UNCORE_FORMAT_ATTR(wrap_mode, wrap_mode, "config:6"); | 1463 | DEFINE_UNCORE_FORMAT_ATTR(wrap_mode, wrap_mode, "config:6"); |
1440 | DEFINE_UNCORE_FORMAT_ATTR(flag_mode, flag_mode, "config:7"); | 1464 | DEFINE_UNCORE_FORMAT_ATTR(flag_mode, flag_mode, "config:7"); |
1441 | DEFINE_UNCORE_FORMAT_ATTR(inc_sel, inc_sel, "config:9-13"); | 1465 | DEFINE_UNCORE_FORMAT_ATTR(inc_sel, inc_sel, "config:9-13"); |
1442 | DEFINE_UNCORE_FORMAT_ATTR(set_flag_sel, set_flag_sel, "config:19-21"); | 1466 | DEFINE_UNCORE_FORMAT_ATTR(set_flag_sel, set_flag_sel, "config:19-21"); |
1443 | DEFINE_UNCORE_FORMAT_ATTR(filter_cfg, filter_cfg, "config2:63"); | 1467 | DEFINE_UNCORE_FORMAT_ATTR(filter_cfg_en, filter_cfg_en, "config2:63"); |
1444 | DEFINE_UNCORE_FORMAT_ATTR(filter_match, filter_match, "config2:0-33"); | 1468 | DEFINE_UNCORE_FORMAT_ATTR(filter_match, filter_match, "config2:0-33"); |
1445 | DEFINE_UNCORE_FORMAT_ATTR(filter_mask, filter_mask, "config2:34-61"); | 1469 | DEFINE_UNCORE_FORMAT_ATTR(filter_mask, filter_mask, "config2:34-61"); |
1446 | DEFINE_UNCORE_FORMAT_ATTR(dsp, dsp, "config1:0-31"); | 1470 | DEFINE_UNCORE_FORMAT_ATTR(dsp, dsp, "config1:0-31"); |
1447 | DEFINE_UNCORE_FORMAT_ATTR(thr, thr, "config1:0-31"); | 1471 | DEFINE_UNCORE_FORMAT_ATTR(thr, thr, "config1:0-31"); |
1448 | DEFINE_UNCORE_FORMAT_ATTR(fvc, fvc, "config1:0-31"); | 1472 | DEFINE_UNCORE_FORMAT_ATTR(fvc, fvc, "config1:0-31"); |
1449 | DEFINE_UNCORE_FORMAT_ATTR(pgt, pgt, "config1:0-31"); | 1473 | DEFINE_UNCORE_FORMAT_ATTR(pgt, pgt, "config1:0-31"); |
1450 | DEFINE_UNCORE_FORMAT_ATTR(map, map, "config1:0-31"); | 1474 | DEFINE_UNCORE_FORMAT_ATTR(map, map, "config1:0-31"); |
1451 | DEFINE_UNCORE_FORMAT_ATTR(iss, iss, "config1:0-31"); | 1475 | DEFINE_UNCORE_FORMAT_ATTR(iss, iss, "config1:0-31"); |
1452 | DEFINE_UNCORE_FORMAT_ATTR(pld, pld, "config1:32-63"); | 1476 | DEFINE_UNCORE_FORMAT_ATTR(pld, pld, "config1:32-63"); |
1453 | 1477 | ||
1454 | static struct attribute *nhmex_uncore_mbox_formats_attr[] = { | 1478 | static struct attribute *nhmex_uncore_mbox_formats_attr[] = { |
1455 | &format_attr_count_mode.attr, | 1479 | &format_attr_count_mode.attr, |
@@ -1458,7 +1482,7 @@ static struct attribute *nhmex_uncore_mbox_formats_attr[] = { | |||
1458 | &format_attr_flag_mode.attr, | 1482 | &format_attr_flag_mode.attr, |
1459 | &format_attr_inc_sel.attr, | 1483 | &format_attr_inc_sel.attr, |
1460 | &format_attr_set_flag_sel.attr, | 1484 | &format_attr_set_flag_sel.attr, |
1461 | &format_attr_filter_cfg.attr, | 1485 | &format_attr_filter_cfg_en.attr, |
1462 | &format_attr_filter_match.attr, | 1486 | &format_attr_filter_match.attr, |
1463 | &format_attr_filter_mask.attr, | 1487 | &format_attr_filter_mask.attr, |
1464 | &format_attr_dsp.attr, | 1488 | &format_attr_dsp.attr, |
@@ -1482,6 +1506,12 @@ static struct uncore_event_desc nhmex_uncore_mbox_events[] = { | |||
1482 | { /* end: all zeroes */ }, | 1506 | { /* end: all zeroes */ }, |
1483 | }; | 1507 | }; |
1484 | 1508 | ||
1509 | static struct uncore_event_desc wsmex_uncore_mbox_events[] = { | ||
1510 | INTEL_UNCORE_EVENT_DESC(bbox_cmds_read, "inc_sel=0xd,fvc=0x5000"), | ||
1511 | INTEL_UNCORE_EVENT_DESC(bbox_cmds_write, "inc_sel=0xd,fvc=0x5040"), | ||
1512 | { /* end: all zeroes */ }, | ||
1513 | }; | ||
1514 | |||
1485 | static struct intel_uncore_ops nhmex_uncore_mbox_ops = { | 1515 | static struct intel_uncore_ops nhmex_uncore_mbox_ops = { |
1486 | NHMEX_UNCORE_OPS_COMMON_INIT(), | 1516 | NHMEX_UNCORE_OPS_COMMON_INIT(), |
1487 | .enable_event = nhmex_mbox_msr_enable_event, | 1517 | .enable_event = nhmex_mbox_msr_enable_event, |
@@ -1513,7 +1543,7 @@ void nhmex_rbox_alter_er(struct intel_uncore_box *box, struct perf_event *event) | |||
1513 | struct hw_perf_event_extra *reg1 = &hwc->extra_reg; | 1543 | struct hw_perf_event_extra *reg1 = &hwc->extra_reg; |
1514 | int port; | 1544 | int port; |
1515 | 1545 | ||
1516 | /* adjust the main event selector */ | 1546 | /* adjust the main event selector and extra register index */ |
1517 | if (reg1->idx % 2) { | 1547 | if (reg1->idx % 2) { |
1518 | reg1->idx--; | 1548 | reg1->idx--; |
1519 | hwc->config -= 1 << NHMEX_R_PMON_CTL_EV_SEL_SHIFT; | 1549 | hwc->config -= 1 << NHMEX_R_PMON_CTL_EV_SEL_SHIFT; |
@@ -1522,29 +1552,17 @@ void nhmex_rbox_alter_er(struct intel_uncore_box *box, struct perf_event *event) | |||
1522 | hwc->config += 1 << NHMEX_R_PMON_CTL_EV_SEL_SHIFT; | 1552 | hwc->config += 1 << NHMEX_R_PMON_CTL_EV_SEL_SHIFT; |
1523 | } | 1553 | } |
1524 | 1554 | ||
1525 | /* adjust address or config of extra register */ | 1555 | /* adjust extra register config */ |
1526 | port = reg1->idx / 6 + box->pmu->pmu_idx * 4; | 1556 | port = reg1->idx / 6 + box->pmu->pmu_idx * 4; |
1527 | switch (reg1->idx % 6) { | 1557 | switch (reg1->idx % 6) { |
1528 | case 0: | ||
1529 | reg1->reg = NHMEX_R_MSR_PORTN_IPERF_CFG0(port); | ||
1530 | break; | ||
1531 | case 1: | ||
1532 | reg1->reg = NHMEX_R_MSR_PORTN_IPERF_CFG1(port); | ||
1533 | break; | ||
1534 | case 2: | 1558 | case 2: |
1535 | /* the 8~15 bits to the 0~7 bits */ | 1559 | /* shift the 8~15 bits to the 0~7 bits */ |
1536 | reg1->config >>= 8; | 1560 | reg1->config >>= 8; |
1537 | break; | 1561 | break; |
1538 | case 3: | 1562 | case 3: |
1539 | /* the 0~7 bits to the 8~15 bits */ | 1563 | /* shift the 0~7 bits to the 8~15 bits */ |
1540 | reg1->config <<= 8; | 1564 | reg1->config <<= 8; |
1541 | break; | 1565 | break; |
1542 | case 4: | ||
1543 | reg1->reg = NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(port); | ||
1544 | break; | ||
1545 | case 5: | ||
1546 | reg1->reg = NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(port); | ||
1547 | break; | ||
1548 | }; | 1566 | }; |
1549 | } | 1567 | } |
1550 | 1568 | ||
@@ -1671,7 +1689,7 @@ static int nhmex_rbox_hw_config(struct intel_uncore_box *box, struct perf_event | |||
1671 | struct hw_perf_event *hwc = &event->hw; | 1689 | struct hw_perf_event *hwc = &event->hw; |
1672 | struct hw_perf_event_extra *reg1 = &event->hw.extra_reg; | 1690 | struct hw_perf_event_extra *reg1 = &event->hw.extra_reg; |
1673 | struct hw_perf_event_extra *reg2 = &event->hw.branch_reg; | 1691 | struct hw_perf_event_extra *reg2 = &event->hw.branch_reg; |
1674 | int port, idx; | 1692 | int idx; |
1675 | 1693 | ||
1676 | idx = (event->hw.config & NHMEX_R_PMON_CTL_EV_SEL_MASK) >> | 1694 | idx = (event->hw.config & NHMEX_R_PMON_CTL_EV_SEL_MASK) >> |
1677 | NHMEX_R_PMON_CTL_EV_SEL_SHIFT; | 1695 | NHMEX_R_PMON_CTL_EV_SEL_SHIFT; |
@@ -1681,27 +1699,11 @@ static int nhmex_rbox_hw_config(struct intel_uncore_box *box, struct perf_event | |||
1681 | reg1->idx = idx; | 1699 | reg1->idx = idx; |
1682 | reg1->config = event->attr.config1; | 1700 | reg1->config = event->attr.config1; |
1683 | 1701 | ||
1684 | port = idx / 6 + box->pmu->pmu_idx * 4; | 1702 | switch (idx % 6) { |
1685 | idx %= 6; | ||
1686 | switch (idx) { | ||
1687 | case 0: | ||
1688 | reg1->reg = NHMEX_R_MSR_PORTN_IPERF_CFG0(port); | ||
1689 | break; | ||
1690 | case 1: | ||
1691 | reg1->reg = NHMEX_R_MSR_PORTN_IPERF_CFG1(port); | ||
1692 | break; | ||
1693 | case 2: | ||
1694 | case 3: | ||
1695 | reg1->reg = NHMEX_R_MSR_PORTN_QLX_CFG(port); | ||
1696 | break; | ||
1697 | case 4: | 1703 | case 4: |
1698 | case 5: | 1704 | case 5: |
1699 | if (idx == 4) | ||
1700 | reg1->reg = NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(port); | ||
1701 | else | ||
1702 | reg1->reg = NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(port); | ||
1703 | reg2->config = event->attr.config2; | ||
1704 | hwc->config |= event->attr.config & (~0ULL << 32); | 1705 | hwc->config |= event->attr.config & (~0ULL << 32); |
1706 | reg2->config = event->attr.config2; | ||
1705 | break; | 1707 | break; |
1706 | }; | 1708 | }; |
1707 | return 0; | 1709 | return 0; |
@@ -1727,28 +1729,34 @@ static void nhmex_rbox_msr_enable_event(struct intel_uncore_box *box, struct per | |||
1727 | struct hw_perf_event *hwc = &event->hw; | 1729 | struct hw_perf_event *hwc = &event->hw; |
1728 | struct hw_perf_event_extra *reg1 = &hwc->extra_reg; | 1730 | struct hw_perf_event_extra *reg1 = &hwc->extra_reg; |
1729 | struct hw_perf_event_extra *reg2 = &hwc->branch_reg; | 1731 | struct hw_perf_event_extra *reg2 = &hwc->branch_reg; |
1730 | int idx, er_idx; | 1732 | int idx, port; |
1731 | 1733 | ||
1732 | idx = reg1->idx % 6; | 1734 | idx = reg1->idx; |
1733 | er_idx = idx; | 1735 | port = idx / 6 + box->pmu->pmu_idx * 4; |
1734 | if (er_idx > 2) | ||
1735 | er_idx--; | ||
1736 | er_idx += (reg1->idx / 6) * 5; | ||
1737 | 1736 | ||
1738 | switch (idx) { | 1737 | switch (idx % 6) { |
1739 | case 0: | 1738 | case 0: |
1739 | wrmsrl(NHMEX_R_MSR_PORTN_IPERF_CFG0(port), reg1->config); | ||
1740 | break; | ||
1740 | case 1: | 1741 | case 1: |
1741 | wrmsrl(reg1->reg, reg1->config); | 1742 | wrmsrl(NHMEX_R_MSR_PORTN_IPERF_CFG1(port), reg1->config); |
1742 | break; | 1743 | break; |
1743 | case 2: | 1744 | case 2: |
1744 | case 3: | 1745 | case 3: |
1745 | wrmsrl(reg1->reg, nhmex_rbox_shared_reg_config(box, er_idx)); | 1746 | wrmsrl(NHMEX_R_MSR_PORTN_QLX_CFG(port), |
1747 | nhmex_rbox_shared_reg_config(box, 2 + (idx / 6) * 5)); | ||
1746 | break; | 1748 | break; |
1747 | case 4: | 1749 | case 4: |
1750 | wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(port), | ||
1751 | hwc->config >> 32); | ||
1752 | wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET1_MATCH(port), reg1->config); | ||
1753 | wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET1_MASK(port), reg2->config); | ||
1754 | break; | ||
1748 | case 5: | 1755 | case 5: |
1749 | wrmsrl(reg1->reg, reg1->config); | 1756 | wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(port), |
1750 | wrmsrl(reg1->reg + 1, hwc->config >> 32); | 1757 | hwc->config >> 32); |
1751 | wrmsrl(reg1->reg + 2, reg2->config); | 1758 | wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET2_MATCH(port), reg1->config); |
1759 | wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET2_MASK(port), reg2->config); | ||
1752 | break; | 1760 | break; |
1753 | }; | 1761 | }; |
1754 | 1762 | ||
@@ -1756,8 +1764,8 @@ static void nhmex_rbox_msr_enable_event(struct intel_uncore_box *box, struct per | |||
1756 | (hwc->config & NHMEX_R_PMON_CTL_EV_SEL_MASK)); | 1764 | (hwc->config & NHMEX_R_PMON_CTL_EV_SEL_MASK)); |
1757 | } | 1765 | } |
1758 | 1766 | ||
1759 | DEFINE_UNCORE_FORMAT_ATTR(xbr_match, xbr_match, "config:32-63"); | 1767 | DEFINE_UNCORE_FORMAT_ATTR(xbr_mm_cfg, xbr_mm_cfg, "config:32-63"); |
1760 | DEFINE_UNCORE_FORMAT_ATTR(xbr_mm_cfg, xbr_mm_cfg, "config1:0-63"); | 1768 | DEFINE_UNCORE_FORMAT_ATTR(xbr_match, xbr_match, "config1:0-63"); |
1761 | DEFINE_UNCORE_FORMAT_ATTR(xbr_mask, xbr_mask, "config2:0-63"); | 1769 | DEFINE_UNCORE_FORMAT_ATTR(xbr_mask, xbr_mask, "config2:0-63"); |
1762 | DEFINE_UNCORE_FORMAT_ATTR(qlx_cfg, qlx_cfg, "config1:0-15"); | 1770 | DEFINE_UNCORE_FORMAT_ATTR(qlx_cfg, qlx_cfg, "config1:0-15"); |
1763 | DEFINE_UNCORE_FORMAT_ATTR(iperf_cfg, iperf_cfg, "config1:0-31"); | 1771 | DEFINE_UNCORE_FORMAT_ATTR(iperf_cfg, iperf_cfg, "config1:0-31"); |
@@ -2303,6 +2311,7 @@ int uncore_pmu_event_init(struct perf_event *event) | |||
2303 | event->hw.idx = -1; | 2311 | event->hw.idx = -1; |
2304 | event->hw.last_tag = ~0ULL; | 2312 | event->hw.last_tag = ~0ULL; |
2305 | event->hw.extra_reg.idx = EXTRA_REG_NONE; | 2313 | event->hw.extra_reg.idx = EXTRA_REG_NONE; |
2314 | event->hw.branch_reg.idx = EXTRA_REG_NONE; | ||
2306 | 2315 | ||
2307 | if (event->attr.config == UNCORE_FIXED_EVENT) { | 2316 | if (event->attr.config == UNCORE_FIXED_EVENT) { |
2308 | /* no fixed counter */ | 2317 | /* no fixed counter */ |
@@ -2373,7 +2382,7 @@ static void __init uncore_type_exit(struct intel_uncore_type *type) | |||
2373 | type->attr_groups[1] = NULL; | 2382 | type->attr_groups[1] = NULL; |
2374 | } | 2383 | } |
2375 | 2384 | ||
2376 | static void uncore_types_exit(struct intel_uncore_type **types) | 2385 | static void __init uncore_types_exit(struct intel_uncore_type **types) |
2377 | { | 2386 | { |
2378 | int i; | 2387 | int i; |
2379 | for (i = 0; types[i]; i++) | 2388 | for (i = 0; types[i]; i++) |
@@ -2814,7 +2823,13 @@ static int __init uncore_cpu_init(void) | |||
2814 | snbep_uncore_cbox.num_boxes = max_cores; | 2823 | snbep_uncore_cbox.num_boxes = max_cores; |
2815 | msr_uncores = snbep_msr_uncores; | 2824 | msr_uncores = snbep_msr_uncores; |
2816 | break; | 2825 | break; |
2817 | case 46: | 2826 | case 46: /* Nehalem-EX */ |
2827 | uncore_nhmex = true; | ||
2828 | case 47: /* Westmere-EX aka. Xeon E7 */ | ||
2829 | if (!uncore_nhmex) | ||
2830 | nhmex_uncore_mbox.event_descs = wsmex_uncore_mbox_events; | ||
2831 | if (nhmex_uncore_cbox.num_boxes > max_cores) | ||
2832 | nhmex_uncore_cbox.num_boxes = max_cores; | ||
2818 | msr_uncores = nhmex_msr_uncores; | 2833 | msr_uncores = nhmex_msr_uncores; |
2819 | break; | 2834 | break; |
2820 | default: | 2835 | default: |
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.h b/arch/x86/kernel/cpu/perf_event_intel_uncore.h index f3851892e077..5b81c1856aac 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.h +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.h | |||
@@ -5,7 +5,7 @@ | |||
5 | #include "perf_event.h" | 5 | #include "perf_event.h" |
6 | 6 | ||
7 | #define UNCORE_PMU_NAME_LEN 32 | 7 | #define UNCORE_PMU_NAME_LEN 32 |
8 | #define UNCORE_PMU_HRTIMER_INTERVAL (60 * NSEC_PER_SEC) | 8 | #define UNCORE_PMU_HRTIMER_INTERVAL (60LL * NSEC_PER_SEC) |
9 | 9 | ||
10 | #define UNCORE_FIXED_EVENT 0xff | 10 | #define UNCORE_FIXED_EVENT 0xff |
11 | #define UNCORE_PMC_IDX_MAX_GENERIC 8 | 11 | #define UNCORE_PMC_IDX_MAX_GENERIC 8 |
@@ -230,6 +230,7 @@ | |||
230 | #define NHMEX_S1_MSR_MASK 0xe5a | 230 | #define NHMEX_S1_MSR_MASK 0xe5a |
231 | 231 | ||
232 | #define NHMEX_S_PMON_MM_CFG_EN (0x1ULL << 63) | 232 | #define NHMEX_S_PMON_MM_CFG_EN (0x1ULL << 63) |
233 | #define NHMEX_S_EVENT_TO_R_PROG_EV 0 | ||
233 | 234 | ||
234 | /* NHM-EX Mbox */ | 235 | /* NHM-EX Mbox */ |
235 | #define NHMEX_M0_MSR_GLOBAL_CTL 0xca0 | 236 | #define NHMEX_M0_MSR_GLOBAL_CTL 0xca0 |
@@ -275,18 +276,12 @@ | |||
275 | NHMEX_M_PMON_CTL_INC_SEL_MASK | \ | 276 | NHMEX_M_PMON_CTL_INC_SEL_MASK | \ |
276 | NHMEX_M_PMON_CTL_SET_FLAG_SEL_MASK) | 277 | NHMEX_M_PMON_CTL_SET_FLAG_SEL_MASK) |
277 | 278 | ||
278 | 279 | #define NHMEX_M_PMON_ZDP_CTL_FVC_MASK (((1 << 11) - 1) | (1 << 23)) | |
279 | #define NHMEX_M_PMON_ZDP_CTL_FVC_FVID_MASK 0x1f | ||
280 | #define NHMEX_M_PMON_ZDP_CTL_FVC_BCMD_MASK (0x7 << 5) | ||
281 | #define NHMEX_M_PMON_ZDP_CTL_FVC_RSP_MASK (0x7 << 8) | ||
282 | #define NHMEX_M_PMON_ZDP_CTL_FVC_PBOX_INIT_ERR (1 << 23) | ||
283 | #define NHMEX_M_PMON_ZDP_CTL_FVC_MASK \ | ||
284 | (NHMEX_M_PMON_ZDP_CTL_FVC_FVID_MASK | \ | ||
285 | NHMEX_M_PMON_ZDP_CTL_FVC_BCMD_MASK | \ | ||
286 | NHMEX_M_PMON_ZDP_CTL_FVC_RSP_MASK | \ | ||
287 | NHMEX_M_PMON_ZDP_CTL_FVC_PBOX_INIT_ERR) | ||
288 | #define NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(n) (0x7 << (11 + 3 * (n))) | 280 | #define NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(n) (0x7 << (11 + 3 * (n))) |
289 | 281 | ||
282 | #define WSMEX_M_PMON_ZDP_CTL_FVC_MASK (((1 << 12) - 1) | (1 << 24)) | ||
283 | #define WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(n) (0x7 << (12 + 3 * (n))) | ||
284 | |||
290 | /* | 285 | /* |
291 | * use the 9~13 bits to select event If the 7th bit is not set, | 286 | * use the 9~13 bits to select event If the 7th bit is not set, |
292 | * otherwise use the 19~21 bits to select event. | 287 | * otherwise use the 19~21 bits to select event. |
@@ -368,6 +363,7 @@ struct intel_uncore_type { | |||
368 | unsigned num_shared_regs:8; | 363 | unsigned num_shared_regs:8; |
369 | unsigned single_fixed:1; | 364 | unsigned single_fixed:1; |
370 | unsigned pair_ctr_ctl:1; | 365 | unsigned pair_ctr_ctl:1; |
366 | unsigned *msr_offsets; | ||
371 | struct event_constraint unconstrainted; | 367 | struct event_constraint unconstrainted; |
372 | struct event_constraint *constraints; | 368 | struct event_constraint *constraints; |
373 | struct intel_uncore_pmu *pmus; | 369 | struct intel_uncore_pmu *pmus; |
@@ -485,29 +481,31 @@ unsigned uncore_pci_perf_ctr(struct intel_uncore_box *box, int idx) | |||
485 | return idx * 8 + box->pmu->type->perf_ctr; | 481 | return idx * 8 + box->pmu->type->perf_ctr; |
486 | } | 482 | } |
487 | 483 | ||
488 | static inline | 484 | static inline unsigned uncore_msr_box_offset(struct intel_uncore_box *box) |
489 | unsigned uncore_msr_box_ctl(struct intel_uncore_box *box) | 485 | { |
486 | struct intel_uncore_pmu *pmu = box->pmu; | ||
487 | return pmu->type->msr_offsets ? | ||
488 | pmu->type->msr_offsets[pmu->pmu_idx] : | ||
489 | pmu->type->msr_offset * pmu->pmu_idx; | ||
490 | } | ||
491 | |||
492 | static inline unsigned uncore_msr_box_ctl(struct intel_uncore_box *box) | ||
490 | { | 493 | { |
491 | if (!box->pmu->type->box_ctl) | 494 | if (!box->pmu->type->box_ctl) |
492 | return 0; | 495 | return 0; |
493 | return box->pmu->type->box_ctl + | 496 | return box->pmu->type->box_ctl + uncore_msr_box_offset(box); |
494 | box->pmu->type->msr_offset * box->pmu->pmu_idx; | ||
495 | } | 497 | } |
496 | 498 | ||
497 | static inline | 499 | static inline unsigned uncore_msr_fixed_ctl(struct intel_uncore_box *box) |
498 | unsigned uncore_msr_fixed_ctl(struct intel_uncore_box *box) | ||
499 | { | 500 | { |
500 | if (!box->pmu->type->fixed_ctl) | 501 | if (!box->pmu->type->fixed_ctl) |
501 | return 0; | 502 | return 0; |
502 | return box->pmu->type->fixed_ctl + | 503 | return box->pmu->type->fixed_ctl + uncore_msr_box_offset(box); |
503 | box->pmu->type->msr_offset * box->pmu->pmu_idx; | ||
504 | } | 504 | } |
505 | 505 | ||
506 | static inline | 506 | static inline unsigned uncore_msr_fixed_ctr(struct intel_uncore_box *box) |
507 | unsigned uncore_msr_fixed_ctr(struct intel_uncore_box *box) | ||
508 | { | 507 | { |
509 | return box->pmu->type->fixed_ctr + | 508 | return box->pmu->type->fixed_ctr + uncore_msr_box_offset(box); |
510 | box->pmu->type->msr_offset * box->pmu->pmu_idx; | ||
511 | } | 509 | } |
512 | 510 | ||
513 | static inline | 511 | static inline |
@@ -515,7 +513,7 @@ unsigned uncore_msr_event_ctl(struct intel_uncore_box *box, int idx) | |||
515 | { | 513 | { |
516 | return box->pmu->type->event_ctl + | 514 | return box->pmu->type->event_ctl + |
517 | (box->pmu->type->pair_ctr_ctl ? 2 * idx : idx) + | 515 | (box->pmu->type->pair_ctr_ctl ? 2 * idx : idx) + |
518 | box->pmu->type->msr_offset * box->pmu->pmu_idx; | 516 | uncore_msr_box_offset(box); |
519 | } | 517 | } |
520 | 518 | ||
521 | static inline | 519 | static inline |
@@ -523,7 +521,7 @@ unsigned uncore_msr_perf_ctr(struct intel_uncore_box *box, int idx) | |||
523 | { | 521 | { |
524 | return box->pmu->type->perf_ctr + | 522 | return box->pmu->type->perf_ctr + |
525 | (box->pmu->type->pair_ctr_ctl ? 2 * idx : idx) + | 523 | (box->pmu->type->pair_ctr_ctl ? 2 * idx : idx) + |
526 | box->pmu->type->msr_offset * box->pmu->pmu_idx; | 524 | uncore_msr_box_offset(box); |
527 | } | 525 | } |
528 | 526 | ||
529 | static inline | 527 | static inline |