diff options
Diffstat (limited to 'arch/x86/kernel/cpu')
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce-apei.c | 42 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event.c | 11 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_p4.c | 1 |
3 files changed, 35 insertions, 19 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce-apei.c b/arch/x86/kernel/cpu/mcheck/mce-apei.c index 8209472b27a5..83930deec3c6 100644 --- a/arch/x86/kernel/cpu/mcheck/mce-apei.c +++ b/arch/x86/kernel/cpu/mcheck/mce-apei.c | |||
@@ -106,24 +106,34 @@ int apei_write_mce(struct mce *m) | |||
106 | ssize_t apei_read_mce(struct mce *m, u64 *record_id) | 106 | ssize_t apei_read_mce(struct mce *m, u64 *record_id) |
107 | { | 107 | { |
108 | struct cper_mce_record rcd; | 108 | struct cper_mce_record rcd; |
109 | ssize_t len; | 109 | int rc, pos; |
110 | 110 | ||
111 | len = erst_read_next(&rcd.hdr, sizeof(rcd)); | 111 | rc = erst_get_record_id_begin(&pos); |
112 | if (len <= 0) | 112 | if (rc) |
113 | return len; | 113 | return rc; |
114 | /* Can not skip other records in storage via ERST unless clear them */ | 114 | retry: |
115 | else if (len != sizeof(rcd) || | 115 | rc = erst_get_record_id_next(&pos, record_id); |
116 | uuid_le_cmp(rcd.hdr.creator_id, CPER_CREATOR_MCE)) { | 116 | if (rc) |
117 | if (printk_ratelimit()) | 117 | goto out; |
118 | pr_warning( | 118 | /* no more record */ |
119 | "MCE-APEI: Can not skip the unknown record in ERST"); | 119 | if (*record_id == APEI_ERST_INVALID_RECORD_ID) |
120 | return -EIO; | 120 | goto out; |
121 | } | 121 | rc = erst_read(*record_id, &rcd.hdr, sizeof(rcd)); |
122 | 122 | /* someone else has cleared the record, try next one */ | |
123 | if (rc == -ENOENT) | ||
124 | goto retry; | ||
125 | else if (rc < 0) | ||
126 | goto out; | ||
127 | /* try to skip other type records in storage */ | ||
128 | else if (rc != sizeof(rcd) || | ||
129 | uuid_le_cmp(rcd.hdr.creator_id, CPER_CREATOR_MCE)) | ||
130 | goto retry; | ||
123 | memcpy(m, &rcd.mce, sizeof(*m)); | 131 | memcpy(m, &rcd.mce, sizeof(*m)); |
124 | *record_id = rcd.hdr.record_id; | 132 | rc = sizeof(*m); |
133 | out: | ||
134 | erst_get_record_id_end(); | ||
125 | 135 | ||
126 | return sizeof(*m); | 136 | return rc; |
127 | } | 137 | } |
128 | 138 | ||
129 | /* Check whether there is record in ERST */ | 139 | /* Check whether there is record in ERST */ |
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 87eab4a27dfc..eed3673a8656 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
@@ -500,12 +500,17 @@ static bool check_hw_exists(void) | |||
500 | return true; | 500 | return true; |
501 | 501 | ||
502 | bios_fail: | 502 | bios_fail: |
503 | printk(KERN_CONT "Broken BIOS detected, using software events only.\n"); | 503 | /* |
504 | * We still allow the PMU driver to operate: | ||
505 | */ | ||
506 | printk(KERN_CONT "Broken BIOS detected, complain to your hardware vendor.\n"); | ||
504 | printk(KERN_ERR FW_BUG "the BIOS has corrupted hw-PMU resources (MSR %x is %Lx)\n", reg, val); | 507 | printk(KERN_ERR FW_BUG "the BIOS has corrupted hw-PMU resources (MSR %x is %Lx)\n", reg, val); |
505 | return false; | 508 | |
509 | return true; | ||
506 | 510 | ||
507 | msr_fail: | 511 | msr_fail: |
508 | printk(KERN_CONT "Broken PMU hardware detected, using software events only.\n"); | 512 | printk(KERN_CONT "Broken PMU hardware detected, using software events only.\n"); |
513 | |||
509 | return false; | 514 | return false; |
510 | } | 515 | } |
511 | 516 | ||
@@ -912,7 +917,7 @@ static inline void x86_assign_hw_event(struct perf_event *event, | |||
912 | hwc->event_base = 0; | 917 | hwc->event_base = 0; |
913 | } else if (hwc->idx >= X86_PMC_IDX_FIXED) { | 918 | } else if (hwc->idx >= X86_PMC_IDX_FIXED) { |
914 | hwc->config_base = MSR_ARCH_PERFMON_FIXED_CTR_CTRL; | 919 | hwc->config_base = MSR_ARCH_PERFMON_FIXED_CTR_CTRL; |
915 | hwc->event_base = MSR_ARCH_PERFMON_FIXED_CTR0; | 920 | hwc->event_base = MSR_ARCH_PERFMON_FIXED_CTR0 + (hwc->idx - X86_PMC_IDX_FIXED); |
916 | } else { | 921 | } else { |
917 | hwc->config_base = x86_pmu_config_addr(hwc->idx); | 922 | hwc->config_base = x86_pmu_config_addr(hwc->idx); |
918 | hwc->event_base = x86_pmu_event_addr(hwc->idx); | 923 | hwc->event_base = x86_pmu_event_addr(hwc->idx); |
diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index 0811f5ebfba6..c2520e178d32 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c | |||
@@ -777,6 +777,7 @@ static inline int p4_pmu_clear_cccr_ovf(struct hw_perf_event *hwc) | |||
777 | * the counter has reached zero value and continued counting before | 777 | * the counter has reached zero value and continued counting before |
778 | * real NMI signal was received: | 778 | * real NMI signal was received: |
779 | */ | 779 | */ |
780 | rdmsrl(hwc->event_base, v); | ||
780 | if (!(v & ARCH_P4_UNFLAGGED_BIT)) | 781 | if (!(v & ARCH_P4_UNFLAGGED_BIT)) |
781 | return 1; | 782 | return 1; |
782 | 783 | ||