diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/ia64/include/asm/acpi.h | 1 | ||||
-rw-r--r-- | arch/ia64/pci/pci.c | 5 | ||||
-rw-r--r-- | arch/x86/include/asm/acpi.h | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/mce.h | 8 | ||||
-rw-r--r-- | arch/x86/kernel/acpi/boot.c | 19 | ||||
-rw-r--r-- | arch/x86/kernel/acpi/sleep.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/Makefile | 2 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce-apei.c | 138 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce-internal.h | 23 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce.c | 79 | ||||
-rw-r--r-- | arch/x86/lguest/boot.c | 1 | ||||
-rw-r--r-- | arch/x86/pci/acpi.c | 5 |
12 files changed, 250 insertions, 35 deletions
diff --git a/arch/ia64/include/asm/acpi.h b/arch/ia64/include/asm/acpi.h index 21adbd7f90f8..837dc82a013e 100644 --- a/arch/ia64/include/asm/acpi.h +++ b/arch/ia64/include/asm/acpi.h | |||
@@ -94,7 +94,6 @@ ia64_acpi_release_global_lock (unsigned int *lock) | |||
94 | #define acpi_noirq 0 /* ACPI always enabled on IA64 */ | 94 | #define acpi_noirq 0 /* ACPI always enabled on IA64 */ |
95 | #define acpi_pci_disabled 0 /* ACPI PCI always enabled on IA64 */ | 95 | #define acpi_pci_disabled 0 /* ACPI PCI always enabled on IA64 */ |
96 | #define acpi_strict 1 /* no ACPI spec workarounds on IA64 */ | 96 | #define acpi_strict 1 /* no ACPI spec workarounds on IA64 */ |
97 | #define acpi_ht 0 /* no HT-only mode on IA64 */ | ||
98 | #endif | 97 | #endif |
99 | #define acpi_processor_cstate_check(x) (x) /* no idle limits on IA64 :) */ | 98 | #define acpi_processor_cstate_check(x) (x) /* no idle limits on IA64 :) */ |
100 | static inline void disable_acpi(void) { } | 99 | static inline void disable_acpi(void) { } |
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 64aff520b899..aa2533ae7e9e 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c | |||
@@ -335,8 +335,11 @@ pcibios_setup_root_windows(struct pci_bus *bus, struct pci_controller *ctrl) | |||
335 | } | 335 | } |
336 | 336 | ||
337 | struct pci_bus * __devinit | 337 | struct pci_bus * __devinit |
338 | pci_acpi_scan_root(struct acpi_device *device, int domain, int bus) | 338 | pci_acpi_scan_root(struct acpi_pci_root *root) |
339 | { | 339 | { |
340 | struct acpi_device *device = root->device; | ||
341 | int domain = root->segment; | ||
342 | int bus = root->secondary.start; | ||
340 | struct pci_controller *controller; | 343 | struct pci_controller *controller; |
341 | unsigned int windows = 0; | 344 | unsigned int windows = 0; |
342 | struct pci_bus *pbus; | 345 | struct pci_bus *pbus; |
diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h index 56f462cf22d2..aa2c39d968fc 100644 --- a/arch/x86/include/asm/acpi.h +++ b/arch/x86/include/asm/acpi.h | |||
@@ -85,7 +85,6 @@ extern int acpi_ioapic; | |||
85 | extern int acpi_noirq; | 85 | extern int acpi_noirq; |
86 | extern int acpi_strict; | 86 | extern int acpi_strict; |
87 | extern int acpi_disabled; | 87 | extern int acpi_disabled; |
88 | extern int acpi_ht; | ||
89 | extern int acpi_pci_disabled; | 88 | extern int acpi_pci_disabled; |
90 | extern int acpi_skip_timer_override; | 89 | extern int acpi_skip_timer_override; |
91 | extern int acpi_use_timer_override; | 90 | extern int acpi_use_timer_override; |
@@ -97,7 +96,6 @@ void acpi_pic_sci_set_trigger(unsigned int, u16); | |||
97 | static inline void disable_acpi(void) | 96 | static inline void disable_acpi(void) |
98 | { | 97 | { |
99 | acpi_disabled = 1; | 98 | acpi_disabled = 1; |
100 | acpi_ht = 0; | ||
101 | acpi_pci_disabled = 1; | 99 | acpi_pci_disabled = 1; |
102 | acpi_noirq = 1; | 100 | acpi_noirq = 1; |
103 | } | 101 | } |
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h index 6c3fdd631ed3..f32a4301c4d4 100644 --- a/arch/x86/include/asm/mce.h +++ b/arch/x86/include/asm/mce.h | |||
@@ -225,5 +225,13 @@ extern void mcheck_intel_therm_init(void); | |||
225 | static inline void mcheck_intel_therm_init(void) { } | 225 | static inline void mcheck_intel_therm_init(void) { } |
226 | #endif | 226 | #endif |
227 | 227 | ||
228 | /* | ||
229 | * Used by APEI to report memory error via /dev/mcelog | ||
230 | */ | ||
231 | |||
232 | struct cper_sec_mem_err; | ||
233 | extern void apei_mce_report_mem_error(int corrected, | ||
234 | struct cper_sec_mem_err *mem_err); | ||
235 | |||
228 | #endif /* __KERNEL__ */ | 236 | #endif /* __KERNEL__ */ |
229 | #endif /* _ASM_X86_MCE_H */ | 237 | #endif /* _ASM_X86_MCE_H */ |
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 488be461a380..60cc4058ed5f 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
@@ -63,7 +63,6 @@ EXPORT_SYMBOL(acpi_disabled); | |||
63 | int acpi_noirq; /* skip ACPI IRQ initialization */ | 63 | int acpi_noirq; /* skip ACPI IRQ initialization */ |
64 | int acpi_pci_disabled; /* skip ACPI PCI scan and IRQ initialization */ | 64 | int acpi_pci_disabled; /* skip ACPI PCI scan and IRQ initialization */ |
65 | EXPORT_SYMBOL(acpi_pci_disabled); | 65 | EXPORT_SYMBOL(acpi_pci_disabled); |
66 | int acpi_ht __initdata = 1; /* enable HT */ | ||
67 | 66 | ||
68 | int acpi_lapic; | 67 | int acpi_lapic; |
69 | int acpi_ioapic; | 68 | int acpi_ioapic; |
@@ -1501,9 +1500,8 @@ void __init acpi_boot_table_init(void) | |||
1501 | 1500 | ||
1502 | /* | 1501 | /* |
1503 | * If acpi_disabled, bail out | 1502 | * If acpi_disabled, bail out |
1504 | * One exception: acpi=ht continues far enough to enumerate LAPICs | ||
1505 | */ | 1503 | */ |
1506 | if (acpi_disabled && !acpi_ht) | 1504 | if (acpi_disabled) |
1507 | return; | 1505 | return; |
1508 | 1506 | ||
1509 | /* | 1507 | /* |
@@ -1534,9 +1532,8 @@ int __init early_acpi_boot_init(void) | |||
1534 | { | 1532 | { |
1535 | /* | 1533 | /* |
1536 | * If acpi_disabled, bail out | 1534 | * If acpi_disabled, bail out |
1537 | * One exception: acpi=ht continues far enough to enumerate LAPICs | ||
1538 | */ | 1535 | */ |
1539 | if (acpi_disabled && !acpi_ht) | 1536 | if (acpi_disabled) |
1540 | return 1; | 1537 | return 1; |
1541 | 1538 | ||
1542 | /* | 1539 | /* |
@@ -1554,9 +1551,8 @@ int __init acpi_boot_init(void) | |||
1554 | 1551 | ||
1555 | /* | 1552 | /* |
1556 | * If acpi_disabled, bail out | 1553 | * If acpi_disabled, bail out |
1557 | * One exception: acpi=ht continues far enough to enumerate LAPICs | ||
1558 | */ | 1554 | */ |
1559 | if (acpi_disabled && !acpi_ht) | 1555 | if (acpi_disabled) |
1560 | return 1; | 1556 | return 1; |
1561 | 1557 | ||
1562 | acpi_table_parse(ACPI_SIG_BOOT, acpi_parse_sbf); | 1558 | acpi_table_parse(ACPI_SIG_BOOT, acpi_parse_sbf); |
@@ -1591,21 +1587,12 @@ static int __init parse_acpi(char *arg) | |||
1591 | /* acpi=force to over-ride black-list */ | 1587 | /* acpi=force to over-ride black-list */ |
1592 | else if (strcmp(arg, "force") == 0) { | 1588 | else if (strcmp(arg, "force") == 0) { |
1593 | acpi_force = 1; | 1589 | acpi_force = 1; |
1594 | acpi_ht = 1; | ||
1595 | acpi_disabled = 0; | 1590 | acpi_disabled = 0; |
1596 | } | 1591 | } |
1597 | /* acpi=strict disables out-of-spec workarounds */ | 1592 | /* acpi=strict disables out-of-spec workarounds */ |
1598 | else if (strcmp(arg, "strict") == 0) { | 1593 | else if (strcmp(arg, "strict") == 0) { |
1599 | acpi_strict = 1; | 1594 | acpi_strict = 1; |
1600 | } | 1595 | } |
1601 | /* Limit ACPI just to boot-time to enable HT */ | ||
1602 | else if (strcmp(arg, "ht") == 0) { | ||
1603 | if (!acpi_force) { | ||
1604 | printk(KERN_WARNING "acpi=ht will be removed in Linux-2.6.35\n"); | ||
1605 | disable_acpi(); | ||
1606 | } | ||
1607 | acpi_ht = 1; | ||
1608 | } | ||
1609 | /* acpi=rsdt use RSDT instead of XSDT */ | 1596 | /* acpi=rsdt use RSDT instead of XSDT */ |
1610 | else if (strcmp(arg, "rsdt") == 0) { | 1597 | else if (strcmp(arg, "rsdt") == 0) { |
1611 | acpi_rsdt_forced = 1; | 1598 | acpi_rsdt_forced = 1; |
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index f9961034e557..82e508677b91 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c | |||
@@ -162,8 +162,6 @@ static int __init acpi_sleep_setup(char *str) | |||
162 | #endif | 162 | #endif |
163 | if (strncmp(str, "old_ordering", 12) == 0) | 163 | if (strncmp(str, "old_ordering", 12) == 0) |
164 | acpi_old_suspend_ordering(); | 164 | acpi_old_suspend_ordering(); |
165 | if (strncmp(str, "sci_force_enable", 16) == 0) | ||
166 | acpi_set_sci_en_on_resume(); | ||
167 | str = strchr(str, ','); | 165 | str = strchr(str, ','); |
168 | if (str != NULL) | 166 | if (str != NULL) |
169 | str += strspn(str, ", \t"); | 167 | str += strspn(str, ", \t"); |
diff --git a/arch/x86/kernel/cpu/mcheck/Makefile b/arch/x86/kernel/cpu/mcheck/Makefile index 4ac6d48fe11b..bb34b03af252 100644 --- a/arch/x86/kernel/cpu/mcheck/Makefile +++ b/arch/x86/kernel/cpu/mcheck/Makefile | |||
@@ -7,3 +7,5 @@ obj-$(CONFIG_X86_MCE_THRESHOLD) += threshold.o | |||
7 | obj-$(CONFIG_X86_MCE_INJECT) += mce-inject.o | 7 | obj-$(CONFIG_X86_MCE_INJECT) += mce-inject.o |
8 | 8 | ||
9 | obj-$(CONFIG_X86_THERMAL_VECTOR) += therm_throt.o | 9 | obj-$(CONFIG_X86_THERMAL_VECTOR) += therm_throt.o |
10 | |||
11 | obj-$(CONFIG_ACPI_APEI) += mce-apei.o | ||
diff --git a/arch/x86/kernel/cpu/mcheck/mce-apei.c b/arch/x86/kernel/cpu/mcheck/mce-apei.c new file mode 100644 index 000000000000..745b54f9be89 --- /dev/null +++ b/arch/x86/kernel/cpu/mcheck/mce-apei.c | |||
@@ -0,0 +1,138 @@ | |||
1 | /* | ||
2 | * Bridge between MCE and APEI | ||
3 | * | ||
4 | * On some machine, corrected memory errors are reported via APEI | ||
5 | * generic hardware error source (GHES) instead of corrected Machine | ||
6 | * Check. These corrected memory errors can be reported to user space | ||
7 | * through /dev/mcelog via faking a corrected Machine Check, so that | ||
8 | * the error memory page can be offlined by /sbin/mcelog if the error | ||
9 | * count for one page is beyond the threshold. | ||
10 | * | ||
11 | * For fatal MCE, save MCE record into persistent storage via ERST, so | ||
12 | * that the MCE record can be logged after reboot via ERST. | ||
13 | * | ||
14 | * Copyright 2010 Intel Corp. | ||
15 | * Author: Huang Ying <ying.huang@intel.com> | ||
16 | * | ||
17 | * This program is free software; you can redistribute it and/or | ||
18 | * modify it under the terms of the GNU General Public License version | ||
19 | * 2 as published by the Free Software Foundation. | ||
20 | * | ||
21 | * This program is distributed in the hope that it will be useful, | ||
22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
24 | * GNU General Public License for more details. | ||
25 | * | ||
26 | * You should have received a copy of the GNU General Public License | ||
27 | * along with this program; if not, write to the Free Software | ||
28 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
29 | */ | ||
30 | |||
31 | #include <linux/kernel.h> | ||
32 | #include <linux/acpi.h> | ||
33 | #include <linux/cper.h> | ||
34 | #include <acpi/apei.h> | ||
35 | #include <asm/mce.h> | ||
36 | |||
37 | #include "mce-internal.h" | ||
38 | |||
39 | void apei_mce_report_mem_error(int corrected, struct cper_sec_mem_err *mem_err) | ||
40 | { | ||
41 | struct mce m; | ||
42 | |||
43 | /* Only corrected MC is reported */ | ||
44 | if (!corrected) | ||
45 | return; | ||
46 | |||
47 | mce_setup(&m); | ||
48 | m.bank = 1; | ||
49 | /* Fake a memory read corrected error with unknown channel */ | ||
50 | m.status = MCI_STATUS_VAL | MCI_STATUS_EN | MCI_STATUS_ADDRV | 0x9f; | ||
51 | m.addr = mem_err->physical_addr; | ||
52 | mce_log(&m); | ||
53 | mce_notify_irq(); | ||
54 | } | ||
55 | EXPORT_SYMBOL_GPL(apei_mce_report_mem_error); | ||
56 | |||
57 | #define CPER_CREATOR_MCE \ | ||
58 | UUID_LE(0x75a574e3, 0x5052, 0x4b29, 0x8a, 0x8e, 0xbe, 0x2c, \ | ||
59 | 0x64, 0x90, 0xb8, 0x9d) | ||
60 | #define CPER_SECTION_TYPE_MCE \ | ||
61 | UUID_LE(0xfe08ffbe, 0x95e4, 0x4be7, 0xbc, 0x73, 0x40, 0x96, \ | ||
62 | 0x04, 0x4a, 0x38, 0xfc) | ||
63 | |||
64 | /* | ||
65 | * CPER specification (in UEFI specification 2.3 appendix N) requires | ||
66 | * byte-packed. | ||
67 | */ | ||
68 | struct cper_mce_record { | ||
69 | struct cper_record_header hdr; | ||
70 | struct cper_section_descriptor sec_hdr; | ||
71 | struct mce mce; | ||
72 | } __packed; | ||
73 | |||
74 | int apei_write_mce(struct mce *m) | ||
75 | { | ||
76 | struct cper_mce_record rcd; | ||
77 | |||
78 | memset(&rcd, 0, sizeof(rcd)); | ||
79 | memcpy(rcd.hdr.signature, CPER_SIG_RECORD, CPER_SIG_SIZE); | ||
80 | rcd.hdr.revision = CPER_RECORD_REV; | ||
81 | rcd.hdr.signature_end = CPER_SIG_END; | ||
82 | rcd.hdr.section_count = 1; | ||
83 | rcd.hdr.error_severity = CPER_SER_FATAL; | ||
84 | /* timestamp, platform_id, partition_id are all invalid */ | ||
85 | rcd.hdr.validation_bits = 0; | ||
86 | rcd.hdr.record_length = sizeof(rcd); | ||
87 | rcd.hdr.creator_id = CPER_CREATOR_MCE; | ||
88 | rcd.hdr.notification_type = CPER_NOTIFY_MCE; | ||
89 | rcd.hdr.record_id = cper_next_record_id(); | ||
90 | rcd.hdr.flags = CPER_HW_ERROR_FLAGS_PREVERR; | ||
91 | |||
92 | rcd.sec_hdr.section_offset = (void *)&rcd.mce - (void *)&rcd; | ||
93 | rcd.sec_hdr.section_length = sizeof(rcd.mce); | ||
94 | rcd.sec_hdr.revision = CPER_SEC_REV; | ||
95 | /* fru_id and fru_text is invalid */ | ||
96 | rcd.sec_hdr.validation_bits = 0; | ||
97 | rcd.sec_hdr.flags = CPER_SEC_PRIMARY; | ||
98 | rcd.sec_hdr.section_type = CPER_SECTION_TYPE_MCE; | ||
99 | rcd.sec_hdr.section_severity = CPER_SER_FATAL; | ||
100 | |||
101 | memcpy(&rcd.mce, m, sizeof(*m)); | ||
102 | |||
103 | return erst_write(&rcd.hdr); | ||
104 | } | ||
105 | |||
106 | ssize_t apei_read_mce(struct mce *m, u64 *record_id) | ||
107 | { | ||
108 | struct cper_mce_record rcd; | ||
109 | ssize_t len; | ||
110 | |||
111 | len = erst_read_next(&rcd.hdr, sizeof(rcd)); | ||
112 | if (len <= 0) | ||
113 | return len; | ||
114 | /* Can not skip other records in storage via ERST unless clear them */ | ||
115 | else if (len != sizeof(rcd) || | ||
116 | uuid_le_cmp(rcd.hdr.creator_id, CPER_CREATOR_MCE)) { | ||
117 | if (printk_ratelimit()) | ||
118 | pr_warning( | ||
119 | "MCE-APEI: Can not skip the unknown record in ERST"); | ||
120 | return -EIO; | ||
121 | } | ||
122 | |||
123 | memcpy(m, &rcd.mce, sizeof(*m)); | ||
124 | *record_id = rcd.hdr.record_id; | ||
125 | |||
126 | return sizeof(*m); | ||
127 | } | ||
128 | |||
129 | /* Check whether there is record in ERST */ | ||
130 | int apei_check_mce(void) | ||
131 | { | ||
132 | return erst_get_record_count(); | ||
133 | } | ||
134 | |||
135 | int apei_clear_mce(u64 record_id) | ||
136 | { | ||
137 | return erst_clear(record_id); | ||
138 | } | ||
diff --git a/arch/x86/kernel/cpu/mcheck/mce-internal.h b/arch/x86/kernel/cpu/mcheck/mce-internal.h index 32996f9fab67..fefcc69ee8b5 100644 --- a/arch/x86/kernel/cpu/mcheck/mce-internal.h +++ b/arch/x86/kernel/cpu/mcheck/mce-internal.h | |||
@@ -28,3 +28,26 @@ extern int mce_ser; | |||
28 | 28 | ||
29 | extern struct mce_bank *mce_banks; | 29 | extern struct mce_bank *mce_banks; |
30 | 30 | ||
31 | #ifdef CONFIG_ACPI_APEI | ||
32 | int apei_write_mce(struct mce *m); | ||
33 | ssize_t apei_read_mce(struct mce *m, u64 *record_id); | ||
34 | int apei_check_mce(void); | ||
35 | int apei_clear_mce(u64 record_id); | ||
36 | #else | ||
37 | static inline int apei_write_mce(struct mce *m) | ||
38 | { | ||
39 | return -EINVAL; | ||
40 | } | ||
41 | static inline ssize_t apei_read_mce(struct mce *m, u64 *record_id) | ||
42 | { | ||
43 | return 0; | ||
44 | } | ||
45 | static inline int apei_check_mce(void) | ||
46 | { | ||
47 | return 0; | ||
48 | } | ||
49 | static inline int apei_clear_mce(u64 record_id) | ||
50 | { | ||
51 | return -EINVAL; | ||
52 | } | ||
53 | #endif | ||
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 7a355ddcc64b..707165dbc203 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c | |||
@@ -264,7 +264,7 @@ static void wait_for_panic(void) | |||
264 | 264 | ||
265 | static void mce_panic(char *msg, struct mce *final, char *exp) | 265 | static void mce_panic(char *msg, struct mce *final, char *exp) |
266 | { | 266 | { |
267 | int i; | 267 | int i, apei_err = 0; |
268 | 268 | ||
269 | if (!fake_panic) { | 269 | if (!fake_panic) { |
270 | /* | 270 | /* |
@@ -287,8 +287,11 @@ static void mce_panic(char *msg, struct mce *final, char *exp) | |||
287 | struct mce *m = &mcelog.entry[i]; | 287 | struct mce *m = &mcelog.entry[i]; |
288 | if (!(m->status & MCI_STATUS_VAL)) | 288 | if (!(m->status & MCI_STATUS_VAL)) |
289 | continue; | 289 | continue; |
290 | if (!(m->status & MCI_STATUS_UC)) | 290 | if (!(m->status & MCI_STATUS_UC)) { |
291 | print_mce(m); | 291 | print_mce(m); |
292 | if (!apei_err) | ||
293 | apei_err = apei_write_mce(m); | ||
294 | } | ||
292 | } | 295 | } |
293 | /* Now print uncorrected but with the final one last */ | 296 | /* Now print uncorrected but with the final one last */ |
294 | for (i = 0; i < MCE_LOG_LEN; i++) { | 297 | for (i = 0; i < MCE_LOG_LEN; i++) { |
@@ -297,11 +300,17 @@ static void mce_panic(char *msg, struct mce *final, char *exp) | |||
297 | continue; | 300 | continue; |
298 | if (!(m->status & MCI_STATUS_UC)) | 301 | if (!(m->status & MCI_STATUS_UC)) |
299 | continue; | 302 | continue; |
300 | if (!final || memcmp(m, final, sizeof(struct mce))) | 303 | if (!final || memcmp(m, final, sizeof(struct mce))) { |
301 | print_mce(m); | 304 | print_mce(m); |
305 | if (!apei_err) | ||
306 | apei_err = apei_write_mce(m); | ||
307 | } | ||
302 | } | 308 | } |
303 | if (final) | 309 | if (final) { |
304 | print_mce(final); | 310 | print_mce(final); |
311 | if (!apei_err) | ||
312 | apei_err = apei_write_mce(final); | ||
313 | } | ||
305 | if (cpu_missing) | 314 | if (cpu_missing) |
306 | printk(KERN_EMERG "Some CPUs didn't answer in synchronization\n"); | 315 | printk(KERN_EMERG "Some CPUs didn't answer in synchronization\n"); |
307 | print_mce_tail(); | 316 | print_mce_tail(); |
@@ -1493,6 +1502,43 @@ static void collect_tscs(void *data) | |||
1493 | rdtscll(cpu_tsc[smp_processor_id()]); | 1502 | rdtscll(cpu_tsc[smp_processor_id()]); |
1494 | } | 1503 | } |
1495 | 1504 | ||
1505 | static int mce_apei_read_done; | ||
1506 | |||
1507 | /* Collect MCE record of previous boot in persistent storage via APEI ERST. */ | ||
1508 | static int __mce_read_apei(char __user **ubuf, size_t usize) | ||
1509 | { | ||
1510 | int rc; | ||
1511 | u64 record_id; | ||
1512 | struct mce m; | ||
1513 | |||
1514 | if (usize < sizeof(struct mce)) | ||
1515 | return -EINVAL; | ||
1516 | |||
1517 | rc = apei_read_mce(&m, &record_id); | ||
1518 | /* Error or no more MCE record */ | ||
1519 | if (rc <= 0) { | ||
1520 | mce_apei_read_done = 1; | ||
1521 | return rc; | ||
1522 | } | ||
1523 | rc = -EFAULT; | ||
1524 | if (copy_to_user(*ubuf, &m, sizeof(struct mce))) | ||
1525 | return rc; | ||
1526 | /* | ||
1527 | * In fact, we should have cleared the record after that has | ||
1528 | * been flushed to the disk or sent to network in | ||
1529 | * /sbin/mcelog, but we have no interface to support that now, | ||
1530 | * so just clear it to avoid duplication. | ||
1531 | */ | ||
1532 | rc = apei_clear_mce(record_id); | ||
1533 | if (rc) { | ||
1534 | mce_apei_read_done = 1; | ||
1535 | return rc; | ||
1536 | } | ||
1537 | *ubuf += sizeof(struct mce); | ||
1538 | |||
1539 | return 0; | ||
1540 | } | ||
1541 | |||
1496 | static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize, | 1542 | static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize, |
1497 | loff_t *off) | 1543 | loff_t *off) |
1498 | { | 1544 | { |
@@ -1506,15 +1552,19 @@ static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize, | |||
1506 | return -ENOMEM; | 1552 | return -ENOMEM; |
1507 | 1553 | ||
1508 | mutex_lock(&mce_read_mutex); | 1554 | mutex_lock(&mce_read_mutex); |
1555 | |||
1556 | if (!mce_apei_read_done) { | ||
1557 | err = __mce_read_apei(&buf, usize); | ||
1558 | if (err || buf != ubuf) | ||
1559 | goto out; | ||
1560 | } | ||
1561 | |||
1509 | next = rcu_dereference_check_mce(mcelog.next); | 1562 | next = rcu_dereference_check_mce(mcelog.next); |
1510 | 1563 | ||
1511 | /* Only supports full reads right now */ | 1564 | /* Only supports full reads right now */ |
1512 | if (*off != 0 || usize < MCE_LOG_LEN*sizeof(struct mce)) { | 1565 | err = -EINVAL; |
1513 | mutex_unlock(&mce_read_mutex); | 1566 | if (*off != 0 || usize < MCE_LOG_LEN*sizeof(struct mce)) |
1514 | kfree(cpu_tsc); | 1567 | goto out; |
1515 | |||
1516 | return -EINVAL; | ||
1517 | } | ||
1518 | 1568 | ||
1519 | err = 0; | 1569 | err = 0; |
1520 | prev = 0; | 1570 | prev = 0; |
@@ -1562,10 +1612,15 @@ timeout: | |||
1562 | memset(&mcelog.entry[i], 0, sizeof(struct mce)); | 1612 | memset(&mcelog.entry[i], 0, sizeof(struct mce)); |
1563 | } | 1613 | } |
1564 | } | 1614 | } |
1615 | |||
1616 | if (err) | ||
1617 | err = -EFAULT; | ||
1618 | |||
1619 | out: | ||
1565 | mutex_unlock(&mce_read_mutex); | 1620 | mutex_unlock(&mce_read_mutex); |
1566 | kfree(cpu_tsc); | 1621 | kfree(cpu_tsc); |
1567 | 1622 | ||
1568 | return err ? -EFAULT : buf - ubuf; | 1623 | return err ? err : buf - ubuf; |
1569 | } | 1624 | } |
1570 | 1625 | ||
1571 | static unsigned int mce_poll(struct file *file, poll_table *wait) | 1626 | static unsigned int mce_poll(struct file *file, poll_table *wait) |
@@ -1573,6 +1628,8 @@ static unsigned int mce_poll(struct file *file, poll_table *wait) | |||
1573 | poll_wait(file, &mce_wait, wait); | 1628 | poll_wait(file, &mce_wait, wait); |
1574 | if (rcu_dereference_check_mce(mcelog.next)) | 1629 | if (rcu_dereference_check_mce(mcelog.next)) |
1575 | return POLLIN | POLLRDNORM; | 1630 | return POLLIN | POLLRDNORM; |
1631 | if (!mce_apei_read_done && apei_check_mce()) | ||
1632 | return POLLIN | POLLRDNORM; | ||
1576 | return 0; | 1633 | return 0; |
1577 | } | 1634 | } |
1578 | 1635 | ||
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index 2bdf628066bd..9257510b4836 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c | |||
@@ -1390,7 +1390,6 @@ __init void lguest_init(void) | |||
1390 | #endif | 1390 | #endif |
1391 | #ifdef CONFIG_ACPI | 1391 | #ifdef CONFIG_ACPI |
1392 | acpi_disabled = 1; | 1392 | acpi_disabled = 1; |
1393 | acpi_ht = 0; | ||
1394 | #endif | 1393 | #endif |
1395 | 1394 | ||
1396 | /* | 1395 | /* |
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index 31930fd30ea9..9dcf43d7d0c0 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c | |||
@@ -224,8 +224,11 @@ res_alloc_fail: | |||
224 | return; | 224 | return; |
225 | } | 225 | } |
226 | 226 | ||
227 | struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum) | 227 | struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root) |
228 | { | 228 | { |
229 | struct acpi_device *device = root->device; | ||
230 | int domain = root->segment; | ||
231 | int busnum = root->secondary.start; | ||
229 | struct pci_bus *bus; | 232 | struct pci_bus *bus; |
230 | struct pci_sysdata *sd; | 233 | struct pci_sysdata *sd; |
231 | int node; | 234 | int node; |