diff options
Diffstat (limited to 'arch')
49 files changed, 5223 insertions, 1803 deletions
diff --git a/arch/avr32/boards/atngw100/Kconfig b/arch/avr32/boards/atngw100/Kconfig index b3f99477bbeb..be27a0218ab4 100644 --- a/arch/avr32/boards/atngw100/Kconfig +++ b/arch/avr32/boards/atngw100/Kconfig | |||
@@ -2,8 +2,15 @@ | |||
2 | 2 | ||
3 | if BOARD_ATNGW100 | 3 | if BOARD_ATNGW100 |
4 | 4 | ||
5 | choice | ||
6 | prompt "Select an NGW100 add-on board to support" | ||
7 | default BOARD_ATNGW100_ADDON_NONE | ||
8 | |||
9 | config BOARD_ATNGW100_ADDON_NONE | ||
10 | bool "None" | ||
11 | |||
5 | config BOARD_ATNGW100_EVKLCD10X | 12 | config BOARD_ATNGW100_EVKLCD10X |
6 | bool "Add support for EVKLCD10X addon board" | 13 | bool "EVKLCD10X addon board" |
7 | help | 14 | help |
8 | This enables support for the EVKLCD100 (QVGA) or EVKLCD101 (VGA) | 15 | This enables support for the EVKLCD100 (QVGA) or EVKLCD101 (VGA) |
9 | addon board for the NGW100. By enabling this the LCD controller and | 16 | addon board for the NGW100. By enabling this the LCD controller and |
@@ -14,7 +21,19 @@ config BOARD_ATNGW100_EVKLCD10X | |||
14 | The MCI pins can be reenabled by editing the "add device function" but | 21 | The MCI pins can be reenabled by editing the "add device function" but |
15 | this may break the setup for other displays that use these pins. | 22 | this may break the setup for other displays that use these pins. |
16 | 23 | ||
17 | Choose 'Y' here if you have a EVKLCD100/101 connected to the NGW100. | 24 | config BOARD_ATNGW100_MRMT |
25 | bool "Mediama RMT1/2 add-on board" | ||
26 | help | ||
27 | This enables support for the Mediama RMT1 or RMT2 board. | ||
28 | RMT provides LCD support, AC97 codec and other | ||
29 | optional peripherals to the Atmel NGW100. | ||
30 | |||
31 | This choice disables the detect pin and the write-protect pin for the | ||
32 | MCI platform device, since it conflicts with the LCD platform device. | ||
33 | The MCI pins can be reenabled by editing the "add device function" but | ||
34 | this may break the setup for other displays that use these pins. | ||
35 | |||
36 | endchoice | ||
18 | 37 | ||
19 | choice | 38 | choice |
20 | prompt "LCD panel resolution on EVKLCD10X" | 39 | prompt "LCD panel resolution on EVKLCD10X" |
@@ -32,4 +51,8 @@ config BOARD_ATNGW100_EVKLCD10X_POW_QVGA | |||
32 | 51 | ||
33 | endchoice | 52 | endchoice |
34 | 53 | ||
54 | if BOARD_ATNGW100_MRMT | ||
55 | source "arch/avr32/boards/atngw100/Kconfig_mrmt" | ||
56 | endif | ||
57 | |||
35 | endif # BOARD_ATNGW100 | 58 | endif # BOARD_ATNGW100 |
diff --git a/arch/avr32/boards/atngw100/Kconfig_mrmt b/arch/avr32/boards/atngw100/Kconfig_mrmt new file mode 100644 index 000000000000..9a199a207f3c --- /dev/null +++ b/arch/avr32/boards/atngw100/Kconfig_mrmt | |||
@@ -0,0 +1,80 @@ | |||
1 | # RMT for NGW100 customization | ||
2 | |||
3 | choice | ||
4 | prompt "RMT Version" | ||
5 | help | ||
6 | Select the RMTx board version. | ||
7 | |||
8 | config BOARD_MRMT_REV1 | ||
9 | bool "RMT1" | ||
10 | config BOARD_MRMT_REV2 | ||
11 | bool "RMT2" | ||
12 | |||
13 | endchoice | ||
14 | |||
15 | config BOARD_MRMT_AC97 | ||
16 | bool "Enable AC97 CODEC" | ||
17 | help | ||
18 | Enable the UCB1400 AC97 CODEC driver. | ||
19 | |||
20 | choice | ||
21 | prompt "Touchscreen Driver" | ||
22 | default BOARD_MRMT_ADS7846_TS | ||
23 | |||
24 | config BOARD_MRMT_UCB1400_TS | ||
25 | bool "Use UCB1400 Touchscreen" | ||
26 | |||
27 | config BOARD_MRMT_ADS7846_TS | ||
28 | bool "Use ADS7846 Touchscreen" | ||
29 | |||
30 | endchoice | ||
31 | |||
32 | choice | ||
33 | prompt "RMTx LCD Selection" | ||
34 | default BOARD_MRMT_LCD_DISABLE | ||
35 | |||
36 | config BOARD_MRMT_LCD_DISABLE | ||
37 | bool "LCD Disabled" | ||
38 | |||
39 | config BOARD_MRMT_LCD_LQ043T3DX0X | ||
40 | bool "Sharp LQ043T3DX0x or compatible" | ||
41 | help | ||
42 | If using RMT2, be sure to load the resistor pack selectors accordingly | ||
43 | |||
44 | if BOARD_MRMT_REV2 | ||
45 | config BOARD_MRMT_LCD_KWH043GM08 | ||
46 | bool "Formike KWH043GM08 or compatible" | ||
47 | help | ||
48 | Be sure to load the RMT2 resistor pack selectors accordingly | ||
49 | endif | ||
50 | |||
51 | endchoice | ||
52 | |||
53 | if !BOARD_MRMT_LCD_DISABLE | ||
54 | config BOARD_MRMT_BL_PWM | ||
55 | bool "Use PWM control for LCD Backlight" | ||
56 | help | ||
57 | Use PWM driver for controlling LCD Backlight. | ||
58 | Otherwise, LCD Backlight is always on. | ||
59 | endif | ||
60 | |||
61 | config BOARD_MRMT_RTC_I2C | ||
62 | bool "Use External RTC on I2C Bus" | ||
63 | help | ||
64 | RMT1 has an optional RTC device on the I2C bus. | ||
65 | It is a SII S35390A. Be sure to select the | ||
66 | matching RTC driver. | ||
67 | |||
68 | choice | ||
69 | prompt "Wireless Module on ttyS2" | ||
70 | default BOARD_MRMT_WIRELESS_ZB | ||
71 | |||
72 | config BOARD_MRMT_WIRELESS_ZB | ||
73 | bool "Use ZigBee/802.15.4 Module" | ||
74 | |||
75 | config BOARD_MRMT_WIRELESS_BT | ||
76 | bool "Use Bluetooth (HCI) Module" | ||
77 | |||
78 | config BOARD_MRMT_WIRELESS_NONE | ||
79 | bool "Not Installed" | ||
80 | endchoice | ||
diff --git a/arch/avr32/boards/atngw100/Makefile b/arch/avr32/boards/atngw100/Makefile index 6376f5322e4d..f4ebe42a8254 100644 --- a/arch/avr32/boards/atngw100/Makefile +++ b/arch/avr32/boards/atngw100/Makefile | |||
@@ -1,2 +1,3 @@ | |||
1 | obj-y += setup.o flash.o | 1 | obj-y += setup.o flash.o |
2 | obj-$(CONFIG_BOARD_ATNGW100_EVKLCD10X) += evklcd10x.o | 2 | obj-$(CONFIG_BOARD_ATNGW100_EVKLCD10X) += evklcd10x.o |
3 | obj-$(CONFIG_BOARD_ATNGW100_MRMT) += mrmt.o | ||
diff --git a/arch/avr32/boards/atngw100/mrmt.c b/arch/avr32/boards/atngw100/mrmt.c new file mode 100644 index 000000000000..bf78e516a85f --- /dev/null +++ b/arch/avr32/boards/atngw100/mrmt.c | |||
@@ -0,0 +1,373 @@ | |||
1 | /* | ||
2 | * Board-specific setup code for Remote Media Terminal 1 (RMT1) | ||
3 | * add-on board for the ATNGW100 Network Gateway | ||
4 | * | ||
5 | * Copyright (C) 2008 Mediama Technologies | ||
6 | * Based on ATNGW100 Network Gateway (Copyright (C) Atmel) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | #include <linux/gpio.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/irq.h> | ||
15 | #include <linux/linkage.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/types.h> | ||
18 | #include <linux/fb.h> | ||
19 | #include <linux/leds.h> | ||
20 | #include <linux/input.h> | ||
21 | #include <linux/gpio_keys.h> | ||
22 | #include <linux/atmel_serial.h> | ||
23 | #include <linux/spi/spi.h> | ||
24 | #include <linux/spi/ads7846.h> | ||
25 | |||
26 | #include <video/atmel_lcdc.h> | ||
27 | #include <sound/atmel-ac97c.h> | ||
28 | |||
29 | #include <asm/delay.h> | ||
30 | #include <asm/io.h> | ||
31 | #include <asm/setup.h> | ||
32 | |||
33 | #include <mach/at32ap700x.h> | ||
34 | #include <mach/board.h> | ||
35 | #include <mach/init.h> | ||
36 | #include <mach/portmux.h> | ||
37 | |||
38 | /* Define board-specifoic GPIO assignments */ | ||
39 | #define PIN_LCD_BL GPIO_PIN_PA(28) | ||
40 | #define PWM_CH_BL 0 /* Must match with GPIO pin definition */ | ||
41 | #define PIN_LCD_DISP GPIO_PIN_PA(31) | ||
42 | #define PIN_AC97_RST_N GPIO_PIN_PA(30) | ||
43 | #define PB_EXTINT_BASE 25 | ||
44 | #define TS_IRQ 0 | ||
45 | #define PIN_TS_EXTINT GPIO_PIN_PB(PB_EXTINT_BASE+TS_IRQ) | ||
46 | #define PIN_PB_LEFT GPIO_PIN_PB(11) | ||
47 | #define PIN_PB_RIGHT GPIO_PIN_PB(12) | ||
48 | #define PIN_PWR_SW_N GPIO_PIN_PB(14) | ||
49 | #define PIN_PWR_ON GPIO_PIN_PB(13) | ||
50 | #define PIN_ZB_RST_N GPIO_PIN_PA(21) | ||
51 | #define PIN_BT_RST GPIO_PIN_PA(22) | ||
52 | #define PIN_LED_SYS GPIO_PIN_PA(16) | ||
53 | #define PIN_LED_A GPIO_PIN_PA(19) | ||
54 | #define PIN_LED_B GPIO_PIN_PE(19) | ||
55 | |||
56 | #ifdef CONFIG_BOARD_MRMT_LCD_LQ043T3DX0X | ||
57 | /* Sharp LQ043T3DX0x (or compatible) panel */ | ||
58 | static struct fb_videomode __initdata lcd_fb_modes[] = { | ||
59 | { | ||
60 | .name = "480x272 @ 59.94Hz", | ||
61 | .refresh = 59.94, | ||
62 | .xres = 480, .yres = 272, | ||
63 | .pixclock = KHZ2PICOS(9000), | ||
64 | |||
65 | .left_margin = 2, .right_margin = 2, | ||
66 | .upper_margin = 3, .lower_margin = 9, | ||
67 | .hsync_len = 41, .vsync_len = 1, | ||
68 | |||
69 | .sync = 0, | ||
70 | .vmode = FB_VMODE_NONINTERLACED, | ||
71 | }, | ||
72 | }; | ||
73 | |||
74 | static struct fb_monspecs __initdata lcd_fb_default_monspecs = { | ||
75 | .manufacturer = "SHA", | ||
76 | .monitor = "LQ043T3DX02", | ||
77 | .modedb = lcd_fb_modes, | ||
78 | .modedb_len = ARRAY_SIZE(lcd_fb_modes), | ||
79 | .hfmin = 14915, | ||
80 | .hfmax = 17638, | ||
81 | .vfmin = 53, | ||
82 | .vfmax = 61, | ||
83 | .dclkmax = 9260000, | ||
84 | }; | ||
85 | |||
86 | static struct atmel_lcdfb_info __initdata rmt_lcdc_data = { | ||
87 | .default_bpp = 24, | ||
88 | .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, | ||
89 | .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT | ||
90 | | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE | ||
91 | | ATMEL_LCDC_INVCLK_NORMAL | ||
92 | | ATMEL_LCDC_MEMOR_BIG), | ||
93 | .lcd_wiring_mode = ATMEL_LCDC_WIRING_RGB, | ||
94 | .default_monspecs = &lcd_fb_default_monspecs, | ||
95 | .guard_time = 2, | ||
96 | }; | ||
97 | #endif | ||
98 | |||
99 | #ifdef CONFIG_BOARD_MRMT_LCD_KWH043GM08 | ||
100 | /* Sharp KWH043GM08-Fxx (or compatible) panel */ | ||
101 | static struct fb_videomode __initdata lcd_fb_modes[] = { | ||
102 | { | ||
103 | .name = "480x272 @ 59.94Hz", | ||
104 | .refresh = 59.94, | ||
105 | .xres = 480, .yres = 272, | ||
106 | .pixclock = KHZ2PICOS(9000), | ||
107 | |||
108 | .left_margin = 2, .right_margin = 2, | ||
109 | .upper_margin = 3, .lower_margin = 9, | ||
110 | .hsync_len = 41, .vsync_len = 1, | ||
111 | |||
112 | .sync = 0, | ||
113 | .vmode = FB_VMODE_NONINTERLACED, | ||
114 | }, | ||
115 | }; | ||
116 | |||
117 | static struct fb_monspecs __initdata lcd_fb_default_monspecs = { | ||
118 | .manufacturer = "FOR", | ||
119 | .monitor = "KWH043GM08", | ||
120 | .modedb = lcd_fb_modes, | ||
121 | .modedb_len = ARRAY_SIZE(lcd_fb_modes), | ||
122 | .hfmin = 14915, | ||
123 | .hfmax = 17638, | ||
124 | .vfmin = 53, | ||
125 | .vfmax = 61, | ||
126 | .dclkmax = 9260000, | ||
127 | }; | ||
128 | |||
129 | static struct atmel_lcdfb_info __initdata rmt_lcdc_data = { | ||
130 | .default_bpp = 24, | ||
131 | .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, | ||
132 | .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT | ||
133 | | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE | ||
134 | | ATMEL_LCDC_INVCLK_INVERTED | ||
135 | | ATMEL_LCDC_MEMOR_BIG), | ||
136 | .lcd_wiring_mode = ATMEL_LCDC_WIRING_RGB, | ||
137 | .default_monspecs = &lcd_fb_default_monspecs, | ||
138 | .guard_time = 2, | ||
139 | }; | ||
140 | #endif | ||
141 | |||
142 | #ifdef CONFIG_BOARD_MRMT_AC97 | ||
143 | static struct ac97c_platform_data __initdata ac97c0_data = { | ||
144 | .reset_pin = PIN_AC97_RST_N, | ||
145 | }; | ||
146 | #endif | ||
147 | |||
148 | #ifdef CONFIG_BOARD_MRMT_UCB1400_TS | ||
149 | /* NOTE: IRQ assignment relies on kernel module parameter */ | ||
150 | static struct platform_device rmt_ts_device = { | ||
151 | .name = "ucb1400_ts", | ||
152 | .id = -1, | ||
153 | } | ||
154 | }; | ||
155 | #endif | ||
156 | |||
157 | #ifdef CONFIG_BOARD_MRMT_BL_PWM | ||
158 | /* PWM LEDs: LCD Backlight, etc */ | ||
159 | static struct gpio_led rmt_pwm_led[] = { | ||
160 | /* here the "gpio" is actually a PWM channel */ | ||
161 | { .name = "backlight", .gpio = PWM_CH_BL, }, | ||
162 | }; | ||
163 | |||
164 | static struct gpio_led_platform_data rmt_pwm_led_data = { | ||
165 | .num_leds = ARRAY_SIZE(rmt_pwm_led), | ||
166 | .leds = rmt_pwm_led, | ||
167 | }; | ||
168 | |||
169 | static struct platform_device rmt_pwm_led_dev = { | ||
170 | .name = "leds-atmel-pwm", | ||
171 | .id = -1, | ||
172 | .dev = { | ||
173 | .platform_data = &rmt_pwm_led_data, | ||
174 | }, | ||
175 | }; | ||
176 | #endif | ||
177 | |||
178 | #ifdef CONFIG_BOARD_MRMT_ADS7846_TS | ||
179 | static int ads7846_pendown_state(void) | ||
180 | { | ||
181 | return !gpio_get_value( PIN_TS_EXTINT ); /* PENIRQ.*/ | ||
182 | } | ||
183 | |||
184 | static struct ads7846_platform_data ads_info = { | ||
185 | .model = 7846, | ||
186 | .keep_vref_on = 0, /* Use external VREF pin */ | ||
187 | .vref_delay_usecs = 0, | ||
188 | .vref_mv = 3300, /* VREF = 3.3V */ | ||
189 | .settle_delay_usecs = 800, | ||
190 | .penirq_recheck_delay_usecs = 800, | ||
191 | .x_plate_ohms = 750, | ||
192 | .y_plate_ohms = 300, | ||
193 | .pressure_max = 4096, | ||
194 | .debounce_max = 1, | ||
195 | .debounce_rep = 0, | ||
196 | .debounce_tol = (~0), | ||
197 | .get_pendown_state = ads7846_pendown_state, | ||
198 | .filter = NULL, | ||
199 | .filter_init = NULL, | ||
200 | }; | ||
201 | |||
202 | static struct spi_board_info spi01_board_info[] __initdata = { | ||
203 | { | ||
204 | .modalias = "ads7846", | ||
205 | .max_speed_hz = 31250*26, | ||
206 | .bus_num = 0, | ||
207 | .chip_select = 1, | ||
208 | .platform_data = &ads_info, | ||
209 | .irq = AT32_EXTINT(TS_IRQ), | ||
210 | }, | ||
211 | }; | ||
212 | #endif | ||
213 | |||
214 | /* GPIO Keys: left, right, power, etc */ | ||
215 | static const struct gpio_keys_button rmt_gpio_keys_buttons[] = { | ||
216 | [0] = { | ||
217 | .type = EV_KEY, | ||
218 | .code = KEY_POWER, | ||
219 | .gpio = PIN_PWR_SW_N, | ||
220 | .active_low = 1, | ||
221 | .desc = "power button", | ||
222 | }, | ||
223 | [1] = { | ||
224 | .type = EV_KEY, | ||
225 | .code = KEY_LEFT, | ||
226 | .gpio = PIN_PB_LEFT, | ||
227 | .active_low = 1, | ||
228 | .desc = "left button", | ||
229 | }, | ||
230 | [2] = { | ||
231 | .type = EV_KEY, | ||
232 | .code = KEY_RIGHT, | ||
233 | .gpio = PIN_PB_RIGHT, | ||
234 | .active_low = 1, | ||
235 | .desc = "right button", | ||
236 | }, | ||
237 | }; | ||
238 | |||
239 | static const struct gpio_keys_platform_data rmt_gpio_keys_data = { | ||
240 | .nbuttons = ARRAY_SIZE(rmt_gpio_keys_buttons), | ||
241 | .buttons = (void *) rmt_gpio_keys_buttons, | ||
242 | }; | ||
243 | |||
244 | static struct platform_device rmt_gpio_keys = { | ||
245 | .name = "gpio-keys", | ||
246 | .id = -1, | ||
247 | .dev = { | ||
248 | .platform_data = (void *) &rmt_gpio_keys_data, | ||
249 | } | ||
250 | }; | ||
251 | |||
252 | #ifdef CONFIG_BOARD_MRMT_RTC_I2C | ||
253 | static struct i2c_board_info __initdata mrmt1_i2c_rtc = { | ||
254 | I2C_BOARD_INFO("s35390a", 0x30), | ||
255 | .irq = 0, | ||
256 | }; | ||
257 | #endif | ||
258 | |||
259 | static void mrmt_power_off(void) | ||
260 | { | ||
261 | /* PWR_ON=0 will force power off */ | ||
262 | gpio_set_value( PIN_PWR_ON, 0 ); | ||
263 | } | ||
264 | |||
265 | static int __init mrmt1_init(void) | ||
266 | { | ||
267 | gpio_set_value( PIN_PWR_ON, 1 ); /* Ensure PWR_ON is enabled */ | ||
268 | |||
269 | pm_power_off = mrmt_power_off; | ||
270 | |||
271 | /* Setup USARTS (other than console) */ | ||
272 | at32_map_usart(2, 1, 0); /* USART 2: /dev/ttyS1, RMT1:DB9M */ | ||
273 | at32_map_usart(3, 2, ATMEL_USART_RTS | ATMEL_USART_CTS); | ||
274 | /* USART 3: /dev/ttyS2, RMT1:Wireless, w/ RTS/CTS */ | ||
275 | at32_add_device_usart(1); | ||
276 | at32_add_device_usart(2); | ||
277 | |||
278 | /* Select GPIO Key pins */ | ||
279 | at32_select_gpio( PIN_PWR_SW_N, AT32_GPIOF_DEGLITCH); | ||
280 | at32_select_gpio( PIN_PB_LEFT, AT32_GPIOF_DEGLITCH); | ||
281 | at32_select_gpio( PIN_PB_RIGHT, AT32_GPIOF_DEGLITCH); | ||
282 | platform_device_register(&rmt_gpio_keys); | ||
283 | |||
284 | #ifdef CONFIG_BOARD_MRMT_RTC_I2C | ||
285 | i2c_register_board_info(0, &mrmt1_i2c_rtc, 1); | ||
286 | #endif | ||
287 | |||
288 | #ifndef CONFIG_BOARD_MRMT_LCD_DISABLE | ||
289 | /* User "alternate" LCDC inferface on Port E & D */ | ||
290 | /* NB: exclude LCDC_CC pin, as NGW100 reserves it for other use */ | ||
291 | at32_add_device_lcdc(0, &rmt_lcdc_data, | ||
292 | fbmem_start, fbmem_size, | ||
293 | (ATMEL_LCDC_ALT_24BIT | ATMEL_LCDC_PE_DVAL ) ); | ||
294 | #endif | ||
295 | |||
296 | #ifdef CONFIG_BOARD_MRMT_AC97 | ||
297 | at32_add_device_ac97c(0, &ac97c0_data, AC97C_BOTH); | ||
298 | #endif | ||
299 | |||
300 | #ifdef CONFIG_BOARD_MRMT_ADS7846_TS | ||
301 | /* Select the Touchscreen interrupt pin mode */ | ||
302 | at32_select_periph( GPIO_PIOB_BASE, 1 << (PB_EXTINT_BASE+TS_IRQ), | ||
303 | GPIO_PERIPH_A, AT32_GPIOF_DEGLITCH); | ||
304 | set_irq_type( AT32_EXTINT(TS_IRQ), IRQ_TYPE_EDGE_FALLING ); | ||
305 | spi_register_board_info(spi01_board_info,ARRAY_SIZE(spi01_board_info)); | ||
306 | #endif | ||
307 | |||
308 | #ifdef CONFIG_BOARD_MRMT_UCB1400_TS | ||
309 | /* Select the Touchscreen interrupt pin mode */ | ||
310 | at32_select_periph( GPIO_PIOB_BASE, 1 << (PB_EXTINT_BASE+TS_IRQ), | ||
311 | GPIO_PERIPH_A, AT32_GPIOF_DEGLITCH); | ||
312 | platform_device_register(&rmt_ts_device); | ||
313 | #endif | ||
314 | |||
315 | at32_select_gpio( PIN_LCD_DISP, AT32_GPIOF_OUTPUT ); | ||
316 | gpio_request( PIN_LCD_DISP, "LCD_DISP" ); | ||
317 | gpio_direction_output( PIN_LCD_DISP, 0 ); /* LCD DISP */ | ||
318 | #ifdef CONFIG_BOARD_MRMT_LCD_DISABLE | ||
319 | /* Keep Backlight and DISP off */ | ||
320 | at32_select_gpio( PIN_LCD_BL, AT32_GPIOF_OUTPUT ); | ||
321 | gpio_request( PIN_LCD_BL, "LCD_BL" ); | ||
322 | gpio_direction_output( PIN_LCD_BL, 0 ); /* Backlight */ | ||
323 | #else | ||
324 | gpio_set_value( PIN_LCD_DISP, 1 ); /* DISP asserted first */ | ||
325 | #ifdef CONFIG_BOARD_MRMT_BL_PWM | ||
326 | /* Use PWM for Backlight controls */ | ||
327 | at32_add_device_pwm(1 << PWM_CH_BL); | ||
328 | platform_device_register(&rmt_pwm_led_dev); | ||
329 | #else | ||
330 | /* Backlight always on */ | ||
331 | udelay( 1 ); | ||
332 | at32_select_gpio( PIN_LCD_BL, AT32_GPIOF_OUTPUT ); | ||
333 | gpio_request( PIN_LCD_BL, "LCD_BL" ); | ||
334 | gpio_direction_output( PIN_LCD_BL, 1 ); | ||
335 | #endif | ||
336 | #endif | ||
337 | |||
338 | /* Make sure BT and Zigbee modules in reset */ | ||
339 | at32_select_gpio( PIN_BT_RST, AT32_GPIOF_OUTPUT ); | ||
340 | gpio_request( PIN_BT_RST, "BT_RST" ); | ||
341 | gpio_direction_output( PIN_BT_RST, 1 ); | ||
342 | /* BT Module in Reset */ | ||
343 | |||
344 | at32_select_gpio( PIN_ZB_RST_N, AT32_GPIOF_OUTPUT ); | ||
345 | gpio_request( PIN_ZB_RST_N, "ZB_RST_N" ); | ||
346 | gpio_direction_output( PIN_ZB_RST_N, 0 ); | ||
347 | /* XBee Module in Reset */ | ||
348 | |||
349 | #ifdef CONFIG_BOARD_MRMT_WIRELESS_ZB | ||
350 | udelay( 1000 ); | ||
351 | /* Unreset the XBee Module */ | ||
352 | gpio_set_value( PIN_ZB_RST_N, 1 ); | ||
353 | #endif | ||
354 | #ifdef CONFIG_BOARD_MRMT_WIRELESS_BT | ||
355 | udelay( 1000 ); | ||
356 | /* Unreset the BT Module */ | ||
357 | gpio_set_value( PIN_BT_RST, 0 ); | ||
358 | #endif | ||
359 | |||
360 | return 0; | ||
361 | } | ||
362 | arch_initcall(mrmt1_init); | ||
363 | |||
364 | static int __init mrmt1_early_init(void) | ||
365 | { | ||
366 | /* To maintain power-on signal in case boot loader did not already */ | ||
367 | at32_select_gpio( PIN_PWR_ON, AT32_GPIOF_OUTPUT ); | ||
368 | gpio_request( PIN_PWR_ON, "PIN_PWR_ON" ); | ||
369 | gpio_direction_output( PIN_PWR_ON, 1 ); | ||
370 | |||
371 | return 0; | ||
372 | } | ||
373 | core_initcall(mrmt1_early_init); | ||
diff --git a/arch/avr32/boards/atngw100/setup.c b/arch/avr32/boards/atngw100/setup.c index 5b022aad4bd9..bc299fbbeb4e 100644 --- a/arch/avr32/boards/atngw100/setup.c +++ b/arch/avr32/boards/atngw100/setup.c | |||
@@ -56,8 +56,13 @@ static struct spi_board_info spi0_board_info[] __initdata = { | |||
56 | static struct mci_platform_data __initdata mci0_data = { | 56 | static struct mci_platform_data __initdata mci0_data = { |
57 | .slot[0] = { | 57 | .slot[0] = { |
58 | .bus_width = 4, | 58 | .bus_width = 4, |
59 | #if defined(CONFIG_BOARD_ATNGW100_EVKLCD10X) || defined(CONFIG_BOARD_ATNGW100_MRMT1) | ||
60 | .detect_pin = GPIO_PIN_NONE, | ||
61 | .wp_pin = GPIO_PIN_NONE, | ||
62 | #else | ||
59 | .detect_pin = GPIO_PIN_PC(25), | 63 | .detect_pin = GPIO_PIN_PC(25), |
60 | .wp_pin = GPIO_PIN_PE(0), | 64 | .wp_pin = GPIO_PIN_PE(0), |
65 | #endif | ||
61 | }, | 66 | }, |
62 | }; | 67 | }; |
63 | 68 | ||
diff --git a/arch/avr32/boards/merisc/setup.c b/arch/avr32/boards/merisc/setup.c index 20b300cf105a..623b077594fc 100644 --- a/arch/avr32/boards/merisc/setup.c +++ b/arch/avr32/boards/merisc/setup.c | |||
@@ -94,9 +94,10 @@ static struct spi_board_info __initdata spi0_board_info[] = { | |||
94 | 94 | ||
95 | static struct mci_platform_data __initdata mci0_data = { | 95 | static struct mci_platform_data __initdata mci0_data = { |
96 | .slot[0] = { | 96 | .slot[0] = { |
97 | .bus_width = 4, | 97 | .bus_width = 4, |
98 | .detect_pin = GPIO_PIN_PE(19), | 98 | .detect_pin = GPIO_PIN_PE(19), |
99 | .wp_pin = GPIO_PIN_PE(20), | 99 | .wp_pin = GPIO_PIN_PE(20), |
100 | .detect_is_active_high = true, | ||
100 | }, | 101 | }, |
101 | }; | 102 | }; |
102 | 103 | ||
diff --git a/arch/avr32/boards/mimc200/setup.c b/arch/avr32/boards/mimc200/setup.c index c1b2175b4fea..523d8e183bef 100644 --- a/arch/avr32/boards/mimc200/setup.c +++ b/arch/avr32/boards/mimc200/setup.c | |||
@@ -43,16 +43,16 @@ unsigned long at32_board_osc_rates[3] = { | |||
43 | /* Initialized by bootloader-specific startup code. */ | 43 | /* Initialized by bootloader-specific startup code. */ |
44 | struct tag *bootloader_tags __initdata; | 44 | struct tag *bootloader_tags __initdata; |
45 | 45 | ||
46 | static struct fb_videomode __initdata tx14d14_modes[] = { | 46 | static struct fb_videomode __initdata pt0434827_modes[] = { |
47 | { | 47 | { |
48 | .name = "640x480 @ 60", | 48 | .name = "480x272 @ 72", |
49 | .refresh = 60, | 49 | .refresh = 72, |
50 | .xres = 640, .yres = 480, | 50 | .xres = 480, .yres = 272, |
51 | .pixclock = KHZ2PICOS(11666), | 51 | .pixclock = KHZ2PICOS(10000), |
52 | 52 | ||
53 | .left_margin = 80, .right_margin = 1, | 53 | .left_margin = 1, .right_margin = 1, |
54 | .upper_margin = 13, .lower_margin = 2, | 54 | .upper_margin = 12, .lower_margin = 1, |
55 | .hsync_len = 64, .vsync_len = 1, | 55 | .hsync_len = 42, .vsync_len = 1, |
56 | 56 | ||
57 | .sync = 0, | 57 | .sync = 0, |
58 | .vmode = FB_VMODE_NONINTERLACED, | 58 | .vmode = FB_VMODE_NONINTERLACED, |
@@ -60,14 +60,14 @@ static struct fb_videomode __initdata tx14d14_modes[] = { | |||
60 | }; | 60 | }; |
61 | 61 | ||
62 | static struct fb_monspecs __initdata mimc200_default_monspecs = { | 62 | static struct fb_monspecs __initdata mimc200_default_monspecs = { |
63 | .manufacturer = "HIT", | 63 | .manufacturer = "PT", |
64 | .monitor = "TX14D14VM1BAB", | 64 | .monitor = "PT0434827-A401", |
65 | .modedb = tx14d14_modes, | 65 | .modedb = pt0434827_modes, |
66 | .modedb_len = ARRAY_SIZE(tx14d14_modes), | 66 | .modedb_len = ARRAY_SIZE(pt0434827_modes), |
67 | .hfmin = 14820, | 67 | .hfmin = 14820, |
68 | .hfmax = 22230, | 68 | .hfmax = 22230, |
69 | .vfmin = 60, | 69 | .vfmin = 60, |
70 | .vfmax = 73.3, | 70 | .vfmax = 85, |
71 | .dclkmax = 25200000, | 71 | .dclkmax = 25200000, |
72 | }; | 72 | }; |
73 | 73 | ||
@@ -228,7 +228,8 @@ static int __init mimc200_init(void) | |||
228 | i2c_register_board_info(0, i2c_info, ARRAY_SIZE(i2c_info)); | 228 | i2c_register_board_info(0, i2c_info, ARRAY_SIZE(i2c_info)); |
229 | 229 | ||
230 | at32_add_device_lcdc(0, &mimc200_lcdc_data, | 230 | at32_add_device_lcdc(0, &mimc200_lcdc_data, |
231 | fbmem_start, fbmem_size, 1); | 231 | fbmem_start, fbmem_size, |
232 | ATMEL_LCDC_CONTROL | ATMEL_LCDC_ALT_CONTROL | ATMEL_LCDC_ALT_24B_DATA); | ||
232 | 233 | ||
233 | return 0; | 234 | return 0; |
234 | } | 235 | } |
diff --git a/arch/avr32/configs/atngw100_mrmt_defconfig b/arch/avr32/configs/atngw100_mrmt_defconfig new file mode 100644 index 000000000000..17b030777d36 --- /dev/null +++ b/arch/avr32/configs/atngw100_mrmt_defconfig | |||
@@ -0,0 +1,1363 @@ | |||
1 | # | ||
2 | # Automatically generated make config: don't edit | ||
3 | # Linux kernel version: 2.6.30-rc1 | ||
4 | # Wed Jun 3 00:24:53 2009 | ||
5 | # | ||
6 | CONFIG_AVR32=y | ||
7 | CONFIG_GENERIC_GPIO=y | ||
8 | CONFIG_GENERIC_HARDIRQS=y | ||
9 | CONFIG_STACKTRACE_SUPPORT=y | ||
10 | CONFIG_LOCKDEP_SUPPORT=y | ||
11 | CONFIG_TRACE_IRQFLAGS_SUPPORT=y | ||
12 | CONFIG_HARDIRQS_SW_RESEND=y | ||
13 | CONFIG_GENERIC_IRQ_PROBE=y | ||
14 | CONFIG_RWSEM_GENERIC_SPINLOCK=y | ||
15 | CONFIG_GENERIC_TIME=y | ||
16 | CONFIG_GENERIC_CLOCKEVENTS=y | ||
17 | # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set | ||
18 | # CONFIG_ARCH_HAS_ILOG2_U32 is not set | ||
19 | # CONFIG_ARCH_HAS_ILOG2_U64 is not set | ||
20 | CONFIG_GENERIC_HWEIGHT=y | ||
21 | CONFIG_GENERIC_CALIBRATE_DELAY=y | ||
22 | CONFIG_GENERIC_BUG=y | ||
23 | CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" | ||
24 | |||
25 | # | ||
26 | # General setup | ||
27 | # | ||
28 | CONFIG_EXPERIMENTAL=y | ||
29 | CONFIG_BROKEN_ON_SMP=y | ||
30 | CONFIG_INIT_ENV_ARG_LIMIT=32 | ||
31 | CONFIG_LOCALVERSION="" | ||
32 | # CONFIG_LOCALVERSION_AUTO is not set | ||
33 | CONFIG_SWAP=y | ||
34 | CONFIG_SYSVIPC=y | ||
35 | CONFIG_SYSVIPC_SYSCTL=y | ||
36 | CONFIG_POSIX_MQUEUE=y | ||
37 | CONFIG_POSIX_MQUEUE_SYSCTL=y | ||
38 | CONFIG_BSD_PROCESS_ACCT=y | ||
39 | CONFIG_BSD_PROCESS_ACCT_V3=y | ||
40 | # CONFIG_TASKSTATS is not set | ||
41 | # CONFIG_AUDIT is not set | ||
42 | |||
43 | # | ||
44 | # RCU Subsystem | ||
45 | # | ||
46 | CONFIG_CLASSIC_RCU=y | ||
47 | # CONFIG_TREE_RCU is not set | ||
48 | # CONFIG_PREEMPT_RCU is not set | ||
49 | # CONFIG_TREE_RCU_TRACE is not set | ||
50 | # CONFIG_PREEMPT_RCU_TRACE is not set | ||
51 | # CONFIG_IKCONFIG is not set | ||
52 | CONFIG_LOG_BUF_SHIFT=14 | ||
53 | CONFIG_GROUP_SCHED=y | ||
54 | CONFIG_FAIR_GROUP_SCHED=y | ||
55 | # CONFIG_RT_GROUP_SCHED is not set | ||
56 | CONFIG_USER_SCHED=y | ||
57 | # CONFIG_CGROUP_SCHED is not set | ||
58 | # CONFIG_CGROUPS is not set | ||
59 | CONFIG_SYSFS_DEPRECATED=y | ||
60 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
61 | # CONFIG_RELAY is not set | ||
62 | # CONFIG_NAMESPACES is not set | ||
63 | CONFIG_BLK_DEV_INITRD=y | ||
64 | CONFIG_INITRAMFS_SOURCE="" | ||
65 | CONFIG_RD_GZIP=y | ||
66 | # CONFIG_RD_BZIP2 is not set | ||
67 | # CONFIG_RD_LZMA is not set | ||
68 | CONFIG_CC_OPTIMIZE_FOR_SIZE=y | ||
69 | CONFIG_SYSCTL=y | ||
70 | CONFIG_ANON_INODES=y | ||
71 | CONFIG_EMBEDDED=y | ||
72 | # CONFIG_SYSCTL_SYSCALL is not set | ||
73 | CONFIG_KALLSYMS=y | ||
74 | # CONFIG_KALLSYMS_ALL is not set | ||
75 | # CONFIG_KALLSYMS_EXTRA_PASS is not set | ||
76 | CONFIG_HOTPLUG=y | ||
77 | CONFIG_PRINTK=y | ||
78 | CONFIG_BUG=y | ||
79 | CONFIG_ELF_CORE=y | ||
80 | # CONFIG_BASE_FULL is not set | ||
81 | CONFIG_FUTEX=y | ||
82 | CONFIG_EPOLL=y | ||
83 | CONFIG_SIGNALFD=y | ||
84 | CONFIG_TIMERFD=y | ||
85 | CONFIG_EVENTFD=y | ||
86 | CONFIG_SHMEM=y | ||
87 | CONFIG_AIO=y | ||
88 | CONFIG_VM_EVENT_COUNTERS=y | ||
89 | # CONFIG_SLUB_DEBUG is not set | ||
90 | CONFIG_COMPAT_BRK=y | ||
91 | # CONFIG_SLAB is not set | ||
92 | CONFIG_SLUB=y | ||
93 | # CONFIG_SLOB is not set | ||
94 | # CONFIG_PROFILING is not set | ||
95 | # CONFIG_MARKERS is not set | ||
96 | CONFIG_HAVE_OPROFILE=y | ||
97 | # CONFIG_KPROBES is not set | ||
98 | CONFIG_HAVE_KPROBES=y | ||
99 | CONFIG_HAVE_CLK=y | ||
100 | # CONFIG_SLOW_WORK is not set | ||
101 | # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set | ||
102 | CONFIG_RT_MUTEXES=y | ||
103 | CONFIG_BASE_SMALL=1 | ||
104 | CONFIG_MODULES=y | ||
105 | # CONFIG_MODULE_FORCE_LOAD is not set | ||
106 | CONFIG_MODULE_UNLOAD=y | ||
107 | CONFIG_MODULE_FORCE_UNLOAD=y | ||
108 | # CONFIG_MODVERSIONS is not set | ||
109 | # CONFIG_MODULE_SRCVERSION_ALL is not set | ||
110 | CONFIG_BLOCK=y | ||
111 | # CONFIG_LBD is not set | ||
112 | # CONFIG_BLK_DEV_BSG is not set | ||
113 | # CONFIG_BLK_DEV_INTEGRITY is not set | ||
114 | |||
115 | # | ||
116 | # IO Schedulers | ||
117 | # | ||
118 | CONFIG_IOSCHED_NOOP=y | ||
119 | # CONFIG_IOSCHED_AS is not set | ||
120 | # CONFIG_IOSCHED_DEADLINE is not set | ||
121 | CONFIG_IOSCHED_CFQ=y | ||
122 | # CONFIG_DEFAULT_AS is not set | ||
123 | # CONFIG_DEFAULT_DEADLINE is not set | ||
124 | CONFIG_DEFAULT_CFQ=y | ||
125 | # CONFIG_DEFAULT_NOOP is not set | ||
126 | CONFIG_DEFAULT_IOSCHED="cfq" | ||
127 | # CONFIG_FREEZER is not set | ||
128 | |||
129 | # | ||
130 | # System Type and features | ||
131 | # | ||
132 | # CONFIG_NO_HZ is not set | ||
133 | # CONFIG_HIGH_RES_TIMERS is not set | ||
134 | CONFIG_GENERIC_CLOCKEVENTS_BUILD=y | ||
135 | CONFIG_SUBARCH_AVR32B=y | ||
136 | CONFIG_MMU=y | ||
137 | CONFIG_PERFORMANCE_COUNTERS=y | ||
138 | CONFIG_PLATFORM_AT32AP=y | ||
139 | CONFIG_CPU_AT32AP700X=y | ||
140 | CONFIG_CPU_AT32AP7000=y | ||
141 | # CONFIG_BOARD_ATSTK1000 is not set | ||
142 | CONFIG_BOARD_ATNGW100=y | ||
143 | # CONFIG_BOARD_HAMMERHEAD is not set | ||
144 | # CONFIG_BOARD_FAVR_32 is not set | ||
145 | # CONFIG_BOARD_MERISC is not set | ||
146 | # CONFIG_BOARD_MIMC200 is not set | ||
147 | # CONFIG_BOARD_ATNGW100_ADDON_NONE is not set | ||
148 | # CONFIG_BOARD_ATNGW100_EVKLCD10X is not set | ||
149 | CONFIG_BOARD_ATNGW100_MRMT=y | ||
150 | CONFIG_BOARD_MRMT_REV1=y | ||
151 | # CONFIG_BOARD_MRMT_REV2 is not set | ||
152 | CONFIG_BOARD_MRMT_AC97=y | ||
153 | # CONFIG_BOARD_MRMT_UCB1400_TS is not set | ||
154 | CONFIG_BOARD_MRMT_ADS7846_TS=y | ||
155 | # CONFIG_BOARD_MRMT_LCD_DISABLE is not set | ||
156 | CONFIG_BOARD_MRMT_LCD_LQ043T3DX0X=y | ||
157 | # CONFIG_BOARD_MRMT_LCD_KWH043GM08 is not set | ||
158 | CONFIG_BOARD_MRMT_BL_PWM=y | ||
159 | CONFIG_BOARD_MRMT_RTC_I2C=y | ||
160 | CONFIG_BOARD_MRMT_WIRELESS_ZB=y | ||
161 | # CONFIG_BOARD_MRMT_WIRELESS_BT is not set | ||
162 | # CONFIG_BOARD_MRMT_WIRELESS_NONE is not set | ||
163 | CONFIG_LOADER_U_BOOT=y | ||
164 | |||
165 | # | ||
166 | # Atmel AVR32 AP options | ||
167 | # | ||
168 | # CONFIG_AP700X_32_BIT_SMC is not set | ||
169 | CONFIG_AP700X_16_BIT_SMC=y | ||
170 | # CONFIG_AP700X_8_BIT_SMC is not set | ||
171 | CONFIG_LOAD_ADDRESS=0x10000000 | ||
172 | CONFIG_ENTRY_ADDRESS=0x90000000 | ||
173 | CONFIG_PHYS_OFFSET=0x10000000 | ||
174 | CONFIG_PREEMPT_NONE=y | ||
175 | # CONFIG_PREEMPT_VOLUNTARY is not set | ||
176 | # CONFIG_PREEMPT is not set | ||
177 | CONFIG_QUICKLIST=y | ||
178 | # CONFIG_HAVE_ARCH_BOOTMEM is not set | ||
179 | # CONFIG_ARCH_HAVE_MEMORY_PRESENT is not set | ||
180 | # CONFIG_NEED_NODE_MEMMAP_SIZE is not set | ||
181 | CONFIG_ARCH_FLATMEM_ENABLE=y | ||
182 | # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set | ||
183 | # CONFIG_ARCH_SPARSEMEM_ENABLE is not set | ||
184 | CONFIG_SELECT_MEMORY_MODEL=y | ||
185 | CONFIG_FLATMEM_MANUAL=y | ||
186 | # CONFIG_DISCONTIGMEM_MANUAL is not set | ||
187 | # CONFIG_SPARSEMEM_MANUAL is not set | ||
188 | CONFIG_FLATMEM=y | ||
189 | CONFIG_FLAT_NODE_MEM_MAP=y | ||
190 | CONFIG_PAGEFLAGS_EXTENDED=y | ||
191 | CONFIG_SPLIT_PTLOCK_CPUS=4 | ||
192 | # CONFIG_PHYS_ADDR_T_64BIT is not set | ||
193 | CONFIG_ZONE_DMA_FLAG=0 | ||
194 | CONFIG_NR_QUICK=2 | ||
195 | CONFIG_VIRT_TO_BUS=y | ||
196 | CONFIG_UNEVICTABLE_LRU=y | ||
197 | CONFIG_HAVE_MLOCK=y | ||
198 | CONFIG_HAVE_MLOCKED_PAGE_BIT=y | ||
199 | # CONFIG_OWNERSHIP_TRACE is not set | ||
200 | # CONFIG_NMI_DEBUGGING is not set | ||
201 | # CONFIG_HZ_100 is not set | ||
202 | CONFIG_HZ_250=y | ||
203 | # CONFIG_HZ_300 is not set | ||
204 | # CONFIG_HZ_1000 is not set | ||
205 | CONFIG_HZ=250 | ||
206 | # CONFIG_SCHED_HRTICK is not set | ||
207 | CONFIG_CMDLINE="" | ||
208 | |||
209 | # | ||
210 | # Power management options | ||
211 | # | ||
212 | CONFIG_PM=y | ||
213 | # CONFIG_PM_DEBUG is not set | ||
214 | # CONFIG_SUSPEND is not set | ||
215 | CONFIG_ARCH_SUSPEND_POSSIBLE=y | ||
216 | |||
217 | # | ||
218 | # CPU Frequency scaling | ||
219 | # | ||
220 | CONFIG_CPU_FREQ=y | ||
221 | CONFIG_CPU_FREQ_TABLE=y | ||
222 | # CONFIG_CPU_FREQ_DEBUG is not set | ||
223 | CONFIG_CPU_FREQ_STAT=y | ||
224 | # CONFIG_CPU_FREQ_STAT_DETAILS is not set | ||
225 | CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y | ||
226 | # CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set | ||
227 | # CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set | ||
228 | # CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set | ||
229 | # CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set | ||
230 | CONFIG_CPU_FREQ_GOV_PERFORMANCE=y | ||
231 | CONFIG_CPU_FREQ_GOV_POWERSAVE=y | ||
232 | CONFIG_CPU_FREQ_GOV_USERSPACE=y | ||
233 | CONFIG_CPU_FREQ_GOV_ONDEMAND=y | ||
234 | # CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set | ||
235 | CONFIG_CPU_FREQ_AT32AP=y | ||
236 | |||
237 | # | ||
238 | # Bus options | ||
239 | # | ||
240 | # CONFIG_ARCH_SUPPORTS_MSI is not set | ||
241 | # CONFIG_PCCARD is not set | ||
242 | |||
243 | # | ||
244 | # Executable file formats | ||
245 | # | ||
246 | CONFIG_BINFMT_ELF=y | ||
247 | # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set | ||
248 | # CONFIG_HAVE_AOUT is not set | ||
249 | # CONFIG_BINFMT_MISC is not set | ||
250 | CONFIG_NET=y | ||
251 | |||
252 | # | ||
253 | # Networking options | ||
254 | # | ||
255 | CONFIG_PACKET=y | ||
256 | CONFIG_PACKET_MMAP=y | ||
257 | CONFIG_UNIX=y | ||
258 | # CONFIG_NET_KEY is not set | ||
259 | CONFIG_INET=y | ||
260 | # CONFIG_IP_MULTICAST is not set | ||
261 | # CONFIG_IP_ADVANCED_ROUTER is not set | ||
262 | CONFIG_IP_FIB_HASH=y | ||
263 | CONFIG_IP_PNP=y | ||
264 | CONFIG_IP_PNP_DHCP=y | ||
265 | # CONFIG_IP_PNP_BOOTP is not set | ||
266 | # CONFIG_IP_PNP_RARP is not set | ||
267 | # CONFIG_NET_IPIP is not set | ||
268 | # CONFIG_NET_IPGRE is not set | ||
269 | # CONFIG_ARPD is not set | ||
270 | CONFIG_SYN_COOKIES=y | ||
271 | # CONFIG_INET_AH is not set | ||
272 | # CONFIG_INET_ESP is not set | ||
273 | # CONFIG_INET_IPCOMP is not set | ||
274 | # CONFIG_INET_XFRM_TUNNEL is not set | ||
275 | # CONFIG_INET_TUNNEL is not set | ||
276 | # CONFIG_INET_XFRM_MODE_TRANSPORT is not set | ||
277 | # CONFIG_INET_XFRM_MODE_TUNNEL is not set | ||
278 | # CONFIG_INET_XFRM_MODE_BEET is not set | ||
279 | # CONFIG_INET_LRO is not set | ||
280 | CONFIG_INET_DIAG=y | ||
281 | CONFIG_INET_TCP_DIAG=y | ||
282 | # CONFIG_TCP_CONG_ADVANCED is not set | ||
283 | CONFIG_TCP_CONG_CUBIC=y | ||
284 | CONFIG_DEFAULT_TCP_CONG="cubic" | ||
285 | # CONFIG_TCP_MD5SIG is not set | ||
286 | # CONFIG_IPV6 is not set | ||
287 | # CONFIG_NETWORK_SECMARK is not set | ||
288 | # CONFIG_NETFILTER is not set | ||
289 | # CONFIG_IP_DCCP is not set | ||
290 | # CONFIG_IP_SCTP is not set | ||
291 | # CONFIG_TIPC is not set | ||
292 | # CONFIG_ATM is not set | ||
293 | # CONFIG_BRIDGE is not set | ||
294 | # CONFIG_NET_DSA is not set | ||
295 | # CONFIG_VLAN_8021Q is not set | ||
296 | # CONFIG_DECNET is not set | ||
297 | # CONFIG_LLC2 is not set | ||
298 | # CONFIG_IPX is not set | ||
299 | # CONFIG_ATALK is not set | ||
300 | # CONFIG_X25 is not set | ||
301 | # CONFIG_LAPB is not set | ||
302 | # CONFIG_ECONET is not set | ||
303 | # CONFIG_WAN_ROUTER is not set | ||
304 | # CONFIG_PHONET is not set | ||
305 | # CONFIG_NET_SCHED is not set | ||
306 | # CONFIG_DCB is not set | ||
307 | |||
308 | # | ||
309 | # Network testing | ||
310 | # | ||
311 | # CONFIG_NET_PKTGEN is not set | ||
312 | # CONFIG_HAMRADIO is not set | ||
313 | # CONFIG_CAN is not set | ||
314 | # CONFIG_IRDA is not set | ||
315 | CONFIG_BT=m | ||
316 | CONFIG_BT_L2CAP=m | ||
317 | # CONFIG_BT_SCO is not set | ||
318 | CONFIG_BT_RFCOMM=m | ||
319 | CONFIG_BT_RFCOMM_TTY=y | ||
320 | # CONFIG_BT_BNEP is not set | ||
321 | CONFIG_BT_HIDP=m | ||
322 | |||
323 | # | ||
324 | # Bluetooth device drivers | ||
325 | # | ||
326 | # CONFIG_BT_HCIBTSDIO is not set | ||
327 | CONFIG_BT_HCIUART=m | ||
328 | CONFIG_BT_HCIUART_H4=y | ||
329 | CONFIG_BT_HCIUART_BCSP=y | ||
330 | # CONFIG_BT_HCIUART_LL is not set | ||
331 | # CONFIG_BT_HCIVHCI is not set | ||
332 | # CONFIG_AF_RXRPC is not set | ||
333 | # CONFIG_WIRELESS is not set | ||
334 | # CONFIG_WIMAX is not set | ||
335 | # CONFIG_RFKILL is not set | ||
336 | # CONFIG_NET_9P is not set | ||
337 | |||
338 | # | ||
339 | # Device Drivers | ||
340 | # | ||
341 | |||
342 | # | ||
343 | # Generic Driver Options | ||
344 | # | ||
345 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | ||
346 | CONFIG_STANDALONE=y | ||
347 | # CONFIG_PREVENT_FIRMWARE_BUILD is not set | ||
348 | # CONFIG_FW_LOADER is not set | ||
349 | # CONFIG_DEBUG_DRIVER is not set | ||
350 | # CONFIG_DEBUG_DEVRES is not set | ||
351 | # CONFIG_SYS_HYPERVISOR is not set | ||
352 | # CONFIG_CONNECTOR is not set | ||
353 | CONFIG_MTD=y | ||
354 | # CONFIG_MTD_DEBUG is not set | ||
355 | # CONFIG_MTD_CONCAT is not set | ||
356 | CONFIG_MTD_PARTITIONS=y | ||
357 | # CONFIG_MTD_TESTS is not set | ||
358 | # CONFIG_MTD_REDBOOT_PARTS is not set | ||
359 | CONFIG_MTD_CMDLINE_PARTS=y | ||
360 | # CONFIG_MTD_AR7_PARTS is not set | ||
361 | |||
362 | # | ||
363 | # User Modules And Translation Layers | ||
364 | # | ||
365 | CONFIG_MTD_CHAR=y | ||
366 | CONFIG_MTD_BLKDEVS=y | ||
367 | CONFIG_MTD_BLOCK=y | ||
368 | # CONFIG_FTL is not set | ||
369 | # CONFIG_NFTL is not set | ||
370 | # CONFIG_INFTL is not set | ||
371 | # CONFIG_RFD_FTL is not set | ||
372 | # CONFIG_SSFDC is not set | ||
373 | # CONFIG_MTD_OOPS is not set | ||
374 | |||
375 | # | ||
376 | # RAM/ROM/Flash chip drivers | ||
377 | # | ||
378 | CONFIG_MTD_CFI=y | ||
379 | # CONFIG_MTD_JEDECPROBE is not set | ||
380 | CONFIG_MTD_GEN_PROBE=y | ||
381 | # CONFIG_MTD_CFI_ADV_OPTIONS is not set | ||
382 | CONFIG_MTD_MAP_BANK_WIDTH_1=y | ||
383 | CONFIG_MTD_MAP_BANK_WIDTH_2=y | ||
384 | CONFIG_MTD_MAP_BANK_WIDTH_4=y | ||
385 | # CONFIG_MTD_MAP_BANK_WIDTH_8 is not set | ||
386 | # CONFIG_MTD_MAP_BANK_WIDTH_16 is not set | ||
387 | # CONFIG_MTD_MAP_BANK_WIDTH_32 is not set | ||
388 | CONFIG_MTD_CFI_I1=y | ||
389 | CONFIG_MTD_CFI_I2=y | ||
390 | # CONFIG_MTD_CFI_I4 is not set | ||
391 | # CONFIG_MTD_CFI_I8 is not set | ||
392 | # CONFIG_MTD_CFI_INTELEXT is not set | ||
393 | CONFIG_MTD_CFI_AMDSTD=y | ||
394 | # CONFIG_MTD_CFI_STAA is not set | ||
395 | CONFIG_MTD_CFI_UTIL=y | ||
396 | # CONFIG_MTD_RAM is not set | ||
397 | # CONFIG_MTD_ROM is not set | ||
398 | # CONFIG_MTD_ABSENT is not set | ||
399 | |||
400 | # | ||
401 | # Mapping drivers for chip access | ||
402 | # | ||
403 | # CONFIG_MTD_COMPLEX_MAPPINGS is not set | ||
404 | CONFIG_MTD_PHYSMAP=y | ||
405 | # CONFIG_MTD_PHYSMAP_COMPAT is not set | ||
406 | # CONFIG_MTD_PLATRAM is not set | ||
407 | |||
408 | # | ||
409 | # Self-contained MTD device drivers | ||
410 | # | ||
411 | CONFIG_MTD_DATAFLASH=y | ||
412 | # CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set | ||
413 | # CONFIG_MTD_DATAFLASH_OTP is not set | ||
414 | # CONFIG_MTD_M25P80 is not set | ||
415 | # CONFIG_MTD_SLRAM is not set | ||
416 | # CONFIG_MTD_PHRAM is not set | ||
417 | # CONFIG_MTD_MTDRAM is not set | ||
418 | # CONFIG_MTD_BLOCK2MTD is not set | ||
419 | |||
420 | # | ||
421 | # Disk-On-Chip Device Drivers | ||
422 | # | ||
423 | # CONFIG_MTD_DOC2000 is not set | ||
424 | # CONFIG_MTD_DOC2001 is not set | ||
425 | # CONFIG_MTD_DOC2001PLUS is not set | ||
426 | # CONFIG_MTD_NAND is not set | ||
427 | # CONFIG_MTD_ONENAND is not set | ||
428 | |||
429 | # | ||
430 | # LPDDR flash memory drivers | ||
431 | # | ||
432 | # CONFIG_MTD_LPDDR is not set | ||
433 | |||
434 | # | ||
435 | # UBI - Unsorted block images | ||
436 | # | ||
437 | # CONFIG_MTD_UBI is not set | ||
438 | # CONFIG_PARPORT is not set | ||
439 | CONFIG_BLK_DEV=y | ||
440 | # CONFIG_BLK_DEV_COW_COMMON is not set | ||
441 | CONFIG_BLK_DEV_LOOP=y | ||
442 | # CONFIG_BLK_DEV_CRYPTOLOOP is not set | ||
443 | # CONFIG_BLK_DEV_NBD is not set | ||
444 | # CONFIG_BLK_DEV_RAM is not set | ||
445 | # CONFIG_CDROM_PKTCDVD is not set | ||
446 | # CONFIG_ATA_OVER_ETH is not set | ||
447 | CONFIG_MISC_DEVICES=y | ||
448 | CONFIG_ATMEL_PWM=y | ||
449 | # CONFIG_ATMEL_TCLIB is not set | ||
450 | # CONFIG_ICS932S401 is not set | ||
451 | # CONFIG_ATMEL_SSC is not set | ||
452 | # CONFIG_ENCLOSURE_SERVICES is not set | ||
453 | # CONFIG_ISL29003 is not set | ||
454 | # CONFIG_C2PORT is not set | ||
455 | |||
456 | # | ||
457 | # EEPROM support | ||
458 | # | ||
459 | # CONFIG_EEPROM_AT24 is not set | ||
460 | # CONFIG_EEPROM_AT25 is not set | ||
461 | # CONFIG_EEPROM_LEGACY is not set | ||
462 | # CONFIG_EEPROM_93CX6 is not set | ||
463 | |||
464 | # | ||
465 | # SCSI device support | ||
466 | # | ||
467 | # CONFIG_RAID_ATTRS is not set | ||
468 | # CONFIG_SCSI is not set | ||
469 | # CONFIG_SCSI_DMA is not set | ||
470 | # CONFIG_SCSI_NETLINK is not set | ||
471 | # CONFIG_ATA is not set | ||
472 | # CONFIG_MD is not set | ||
473 | CONFIG_NETDEVICES=y | ||
474 | CONFIG_COMPAT_NET_DEV_OPS=y | ||
475 | # CONFIG_DUMMY is not set | ||
476 | # CONFIG_BONDING is not set | ||
477 | # CONFIG_MACVLAN is not set | ||
478 | # CONFIG_EQUALIZER is not set | ||
479 | # CONFIG_TUN is not set | ||
480 | # CONFIG_VETH is not set | ||
481 | CONFIG_PHYLIB=y | ||
482 | |||
483 | # | ||
484 | # MII PHY device drivers | ||
485 | # | ||
486 | # CONFIG_MARVELL_PHY is not set | ||
487 | # CONFIG_DAVICOM_PHY is not set | ||
488 | # CONFIG_QSEMI_PHY is not set | ||
489 | # CONFIG_LXT_PHY is not set | ||
490 | # CONFIG_CICADA_PHY is not set | ||
491 | # CONFIG_VITESSE_PHY is not set | ||
492 | # CONFIG_SMSC_PHY is not set | ||
493 | # CONFIG_BROADCOM_PHY is not set | ||
494 | # CONFIG_ICPLUS_PHY is not set | ||
495 | # CONFIG_REALTEK_PHY is not set | ||
496 | # CONFIG_NATIONAL_PHY is not set | ||
497 | # CONFIG_STE10XP is not set | ||
498 | # CONFIG_LSI_ET1011C_PHY is not set | ||
499 | # CONFIG_FIXED_PHY is not set | ||
500 | # CONFIG_MDIO_BITBANG is not set | ||
501 | CONFIG_NET_ETHERNET=y | ||
502 | # CONFIG_MII is not set | ||
503 | CONFIG_MACB=y | ||
504 | # CONFIG_ENC28J60 is not set | ||
505 | # CONFIG_ETHOC is not set | ||
506 | # CONFIG_DNET is not set | ||
507 | # CONFIG_IBM_NEW_EMAC_ZMII is not set | ||
508 | # CONFIG_IBM_NEW_EMAC_RGMII is not set | ||
509 | # CONFIG_IBM_NEW_EMAC_TAH is not set | ||
510 | # CONFIG_IBM_NEW_EMAC_EMAC4 is not set | ||
511 | # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set | ||
512 | # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set | ||
513 | # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set | ||
514 | # CONFIG_B44 is not set | ||
515 | # CONFIG_NETDEV_1000 is not set | ||
516 | # CONFIG_NETDEV_10000 is not set | ||
517 | |||
518 | # | ||
519 | # Wireless LAN | ||
520 | # | ||
521 | # CONFIG_WLAN_PRE80211 is not set | ||
522 | # CONFIG_WLAN_80211 is not set | ||
523 | |||
524 | # | ||
525 | # Enable WiMAX (Networking options) to see the WiMAX drivers | ||
526 | # | ||
527 | # CONFIG_WAN is not set | ||
528 | # CONFIG_PPP is not set | ||
529 | # CONFIG_SLIP is not set | ||
530 | # CONFIG_NETCONSOLE is not set | ||
531 | # CONFIG_NETPOLL is not set | ||
532 | # CONFIG_NET_POLL_CONTROLLER is not set | ||
533 | # CONFIG_ISDN is not set | ||
534 | # CONFIG_PHONE is not set | ||
535 | |||
536 | # | ||
537 | # Input device support | ||
538 | # | ||
539 | CONFIG_INPUT=y | ||
540 | # CONFIG_INPUT_FF_MEMLESS is not set | ||
541 | # CONFIG_INPUT_POLLDEV is not set | ||
542 | |||
543 | # | ||
544 | # Userland interfaces | ||
545 | # | ||
546 | # CONFIG_INPUT_MOUSEDEV is not set | ||
547 | # CONFIG_INPUT_JOYDEV is not set | ||
548 | CONFIG_INPUT_EVDEV=y | ||
549 | # CONFIG_INPUT_EVBUG is not set | ||
550 | |||
551 | # | ||
552 | # Input Device Drivers | ||
553 | # | ||
554 | CONFIG_INPUT_KEYBOARD=y | ||
555 | # CONFIG_KEYBOARD_ATKBD is not set | ||
556 | # CONFIG_KEYBOARD_SUNKBD is not set | ||
557 | # CONFIG_KEYBOARD_LKKBD is not set | ||
558 | # CONFIG_KEYBOARD_XTKBD is not set | ||
559 | # CONFIG_KEYBOARD_NEWTON is not set | ||
560 | # CONFIG_KEYBOARD_STOWAWAY is not set | ||
561 | CONFIG_KEYBOARD_GPIO=y | ||
562 | # CONFIG_INPUT_MOUSE is not set | ||
563 | # CONFIG_INPUT_JOYSTICK is not set | ||
564 | # CONFIG_INPUT_TABLET is not set | ||
565 | CONFIG_INPUT_TOUCHSCREEN=y | ||
566 | CONFIG_TOUCHSCREEN_ADS7846=m | ||
567 | # CONFIG_TOUCHSCREEN_FUJITSU is not set | ||
568 | # CONFIG_TOUCHSCREEN_GUNZE is not set | ||
569 | # CONFIG_TOUCHSCREEN_ELO is not set | ||
570 | # CONFIG_TOUCHSCREEN_WACOM_W8001 is not set | ||
571 | # CONFIG_TOUCHSCREEN_MTOUCH is not set | ||
572 | # CONFIG_TOUCHSCREEN_INEXIO is not set | ||
573 | # CONFIG_TOUCHSCREEN_MK712 is not set | ||
574 | # CONFIG_TOUCHSCREEN_PENMOUNT is not set | ||
575 | # CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set | ||
576 | # CONFIG_TOUCHSCREEN_TOUCHWIN is not set | ||
577 | # CONFIG_TOUCHSCREEN_WM97XX is not set | ||
578 | # CONFIG_TOUCHSCREEN_TOUCHIT213 is not set | ||
579 | # CONFIG_TOUCHSCREEN_TSC2007 is not set | ||
580 | # CONFIG_INPUT_MISC is not set | ||
581 | |||
582 | # | ||
583 | # Hardware I/O ports | ||
584 | # | ||
585 | # CONFIG_SERIO is not set | ||
586 | # CONFIG_GAMEPORT is not set | ||
587 | |||
588 | # | ||
589 | # Character devices | ||
590 | # | ||
591 | CONFIG_VT=y | ||
592 | CONFIG_CONSOLE_TRANSLATIONS=y | ||
593 | CONFIG_VT_CONSOLE=y | ||
594 | CONFIG_HW_CONSOLE=y | ||
595 | CONFIG_VT_HW_CONSOLE_BINDING=y | ||
596 | CONFIG_DEVKMEM=y | ||
597 | # CONFIG_SERIAL_NONSTANDARD is not set | ||
598 | |||
599 | # | ||
600 | # Serial drivers | ||
601 | # | ||
602 | # CONFIG_SERIAL_8250 is not set | ||
603 | |||
604 | # | ||
605 | # Non-8250 serial port support | ||
606 | # | ||
607 | CONFIG_SERIAL_ATMEL=y | ||
608 | CONFIG_SERIAL_ATMEL_CONSOLE=y | ||
609 | CONFIG_SERIAL_ATMEL_PDC=y | ||
610 | # CONFIG_SERIAL_ATMEL_TTYAT is not set | ||
611 | # CONFIG_SERIAL_MAX3100 is not set | ||
612 | CONFIG_SERIAL_CORE=y | ||
613 | CONFIG_SERIAL_CORE_CONSOLE=y | ||
614 | CONFIG_UNIX98_PTYS=y | ||
615 | # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set | ||
616 | # CONFIG_LEGACY_PTYS is not set | ||
617 | # CONFIG_IPMI_HANDLER is not set | ||
618 | # CONFIG_HW_RANDOM is not set | ||
619 | # CONFIG_R3964 is not set | ||
620 | # CONFIG_RAW_DRIVER is not set | ||
621 | # CONFIG_TCG_TPM is not set | ||
622 | CONFIG_I2C=y | ||
623 | CONFIG_I2C_BOARDINFO=y | ||
624 | CONFIG_I2C_CHARDEV=y | ||
625 | CONFIG_I2C_HELPER_AUTO=y | ||
626 | CONFIG_I2C_ALGOBIT=y | ||
627 | |||
628 | # | ||
629 | # I2C Hardware Bus support | ||
630 | # | ||
631 | |||
632 | # | ||
633 | # I2C system bus drivers (mostly embedded / system-on-chip) | ||
634 | # | ||
635 | CONFIG_I2C_GPIO=y | ||
636 | # CONFIG_I2C_OCORES is not set | ||
637 | # CONFIG_I2C_SIMTEC is not set | ||
638 | |||
639 | # | ||
640 | # External I2C/SMBus adapter drivers | ||
641 | # | ||
642 | # CONFIG_I2C_PARPORT_LIGHT is not set | ||
643 | # CONFIG_I2C_TAOS_EVM is not set | ||
644 | |||
645 | # | ||
646 | # Other I2C/SMBus bus drivers | ||
647 | # | ||
648 | # CONFIG_I2C_PCA_PLATFORM is not set | ||
649 | # CONFIG_I2C_STUB is not set | ||
650 | |||
651 | # | ||
652 | # Miscellaneous I2C Chip support | ||
653 | # | ||
654 | # CONFIG_DS1682 is not set | ||
655 | # CONFIG_SENSORS_PCF8574 is not set | ||
656 | # CONFIG_PCF8575 is not set | ||
657 | # CONFIG_SENSORS_PCA9539 is not set | ||
658 | # CONFIG_SENSORS_MAX6875 is not set | ||
659 | # CONFIG_SENSORS_TSL2550 is not set | ||
660 | # CONFIG_I2C_DEBUG_CORE is not set | ||
661 | # CONFIG_I2C_DEBUG_ALGO is not set | ||
662 | # CONFIG_I2C_DEBUG_BUS is not set | ||
663 | # CONFIG_I2C_DEBUG_CHIP is not set | ||
664 | CONFIG_SPI=y | ||
665 | # CONFIG_SPI_DEBUG is not set | ||
666 | CONFIG_SPI_MASTER=y | ||
667 | |||
668 | # | ||
669 | # SPI Master Controller Drivers | ||
670 | # | ||
671 | CONFIG_SPI_ATMEL=y | ||
672 | # CONFIG_SPI_BITBANG is not set | ||
673 | # CONFIG_SPI_GPIO is not set | ||
674 | |||
675 | # | ||
676 | # SPI Protocol Masters | ||
677 | # | ||
678 | CONFIG_SPI_SPIDEV=y | ||
679 | # CONFIG_SPI_TLE62X0 is not set | ||
680 | CONFIG_ARCH_REQUIRE_GPIOLIB=y | ||
681 | CONFIG_GPIOLIB=y | ||
682 | # CONFIG_DEBUG_GPIO is not set | ||
683 | # CONFIG_GPIO_SYSFS is not set | ||
684 | |||
685 | # | ||
686 | # Memory mapped GPIO expanders: | ||
687 | # | ||
688 | |||
689 | # | ||
690 | # I2C GPIO expanders: | ||
691 | # | ||
692 | # CONFIG_GPIO_MAX732X is not set | ||
693 | # CONFIG_GPIO_PCA953X is not set | ||
694 | # CONFIG_GPIO_PCF857X is not set | ||
695 | |||
696 | # | ||
697 | # PCI GPIO expanders: | ||
698 | # | ||
699 | |||
700 | # | ||
701 | # SPI GPIO expanders: | ||
702 | # | ||
703 | # CONFIG_GPIO_MAX7301 is not set | ||
704 | # CONFIG_GPIO_MCP23S08 is not set | ||
705 | # CONFIG_W1 is not set | ||
706 | # CONFIG_POWER_SUPPLY is not set | ||
707 | CONFIG_HWMON=y | ||
708 | # CONFIG_HWMON_VID is not set | ||
709 | # CONFIG_SENSORS_AD7414 is not set | ||
710 | # CONFIG_SENSORS_AD7418 is not set | ||
711 | # CONFIG_SENSORS_ADCXX is not set | ||
712 | # CONFIG_SENSORS_ADM1021 is not set | ||
713 | # CONFIG_SENSORS_ADM1025 is not set | ||
714 | # CONFIG_SENSORS_ADM1026 is not set | ||
715 | # CONFIG_SENSORS_ADM1029 is not set | ||
716 | # CONFIG_SENSORS_ADM1031 is not set | ||
717 | # CONFIG_SENSORS_ADM9240 is not set | ||
718 | # CONFIG_SENSORS_ADT7462 is not set | ||
719 | # CONFIG_SENSORS_ADT7470 is not set | ||
720 | # CONFIG_SENSORS_ADT7473 is not set | ||
721 | # CONFIG_SENSORS_ADT7475 is not set | ||
722 | # CONFIG_SENSORS_ATXP1 is not set | ||
723 | # CONFIG_SENSORS_DS1621 is not set | ||
724 | # CONFIG_SENSORS_F71805F is not set | ||
725 | # CONFIG_SENSORS_F71882FG is not set | ||
726 | # CONFIG_SENSORS_F75375S is not set | ||
727 | # CONFIG_SENSORS_G760A is not set | ||
728 | # CONFIG_SENSORS_GL518SM is not set | ||
729 | # CONFIG_SENSORS_GL520SM is not set | ||
730 | # CONFIG_SENSORS_IT87 is not set | ||
731 | # CONFIG_SENSORS_LM63 is not set | ||
732 | # CONFIG_SENSORS_LM70 is not set | ||
733 | # CONFIG_SENSORS_LM75 is not set | ||
734 | # CONFIG_SENSORS_LM77 is not set | ||
735 | # CONFIG_SENSORS_LM78 is not set | ||
736 | # CONFIG_SENSORS_LM80 is not set | ||
737 | # CONFIG_SENSORS_LM83 is not set | ||
738 | # CONFIG_SENSORS_LM85 is not set | ||
739 | # CONFIG_SENSORS_LM87 is not set | ||
740 | # CONFIG_SENSORS_LM90 is not set | ||
741 | # CONFIG_SENSORS_LM92 is not set | ||
742 | # CONFIG_SENSORS_LM93 is not set | ||
743 | # CONFIG_SENSORS_LTC4215 is not set | ||
744 | # CONFIG_SENSORS_LTC4245 is not set | ||
745 | # CONFIG_SENSORS_LM95241 is not set | ||
746 | # CONFIG_SENSORS_MAX1111 is not set | ||
747 | # CONFIG_SENSORS_MAX1619 is not set | ||
748 | # CONFIG_SENSORS_MAX6650 is not set | ||
749 | # CONFIG_SENSORS_PC87360 is not set | ||
750 | # CONFIG_SENSORS_PC87427 is not set | ||
751 | # CONFIG_SENSORS_PCF8591 is not set | ||
752 | # CONFIG_SENSORS_DME1737 is not set | ||
753 | # CONFIG_SENSORS_SMSC47M1 is not set | ||
754 | # CONFIG_SENSORS_SMSC47M192 is not set | ||
755 | # CONFIG_SENSORS_SMSC47B397 is not set | ||
756 | # CONFIG_SENSORS_ADS7828 is not set | ||
757 | # CONFIG_SENSORS_THMC50 is not set | ||
758 | # CONFIG_SENSORS_VT1211 is not set | ||
759 | # CONFIG_SENSORS_W83781D is not set | ||
760 | # CONFIG_SENSORS_W83791D is not set | ||
761 | # CONFIG_SENSORS_W83792D is not set | ||
762 | # CONFIG_SENSORS_W83793 is not set | ||
763 | # CONFIG_SENSORS_W83L785TS is not set | ||
764 | # CONFIG_SENSORS_W83L786NG is not set | ||
765 | # CONFIG_SENSORS_W83627HF is not set | ||
766 | # CONFIG_SENSORS_W83627EHF is not set | ||
767 | # CONFIG_SENSORS_LIS3_SPI is not set | ||
768 | # CONFIG_HWMON_DEBUG_CHIP is not set | ||
769 | # CONFIG_THERMAL is not set | ||
770 | # CONFIG_THERMAL_HWMON is not set | ||
771 | CONFIG_WATCHDOG=y | ||
772 | # CONFIG_WATCHDOG_NOWAYOUT is not set | ||
773 | |||
774 | # | ||
775 | # Watchdog Device Drivers | ||
776 | # | ||
777 | # CONFIG_SOFT_WATCHDOG is not set | ||
778 | CONFIG_AT32AP700X_WDT=y | ||
779 | CONFIG_SSB_POSSIBLE=y | ||
780 | |||
781 | # | ||
782 | # Sonics Silicon Backplane | ||
783 | # | ||
784 | # CONFIG_SSB is not set | ||
785 | |||
786 | # | ||
787 | # Multifunction device drivers | ||
788 | # | ||
789 | # CONFIG_MFD_CORE is not set | ||
790 | # CONFIG_MFD_SM501 is not set | ||
791 | # CONFIG_HTC_PASIC3 is not set | ||
792 | # CONFIG_UCB1400_CORE is not set | ||
793 | # CONFIG_TPS65010 is not set | ||
794 | # CONFIG_TWL4030_CORE is not set | ||
795 | # CONFIG_MFD_TMIO is not set | ||
796 | # CONFIG_PMIC_DA903X is not set | ||
797 | # CONFIG_MFD_WM8400 is not set | ||
798 | # CONFIG_MFD_WM8350_I2C is not set | ||
799 | # CONFIG_MFD_PCF50633 is not set | ||
800 | # CONFIG_REGULATOR is not set | ||
801 | |||
802 | # | ||
803 | # Multimedia devices | ||
804 | # | ||
805 | |||
806 | # | ||
807 | # Multimedia core support | ||
808 | # | ||
809 | # CONFIG_VIDEO_DEV is not set | ||
810 | # CONFIG_DVB_CORE is not set | ||
811 | # CONFIG_VIDEO_MEDIA is not set | ||
812 | |||
813 | # | ||
814 | # Multimedia drivers | ||
815 | # | ||
816 | # CONFIG_DAB is not set | ||
817 | |||
818 | # | ||
819 | # Graphics support | ||
820 | # | ||
821 | # CONFIG_VGASTATE is not set | ||
822 | # CONFIG_VIDEO_OUTPUT_CONTROL is not set | ||
823 | CONFIG_FB=y | ||
824 | # CONFIG_FIRMWARE_EDID is not set | ||
825 | # CONFIG_FB_DDC is not set | ||
826 | # CONFIG_FB_BOOT_VESA_SUPPORT is not set | ||
827 | CONFIG_FB_CFB_FILLRECT=y | ||
828 | CONFIG_FB_CFB_COPYAREA=y | ||
829 | CONFIG_FB_CFB_IMAGEBLIT=y | ||
830 | # CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set | ||
831 | # CONFIG_FB_SYS_FILLRECT is not set | ||
832 | # CONFIG_FB_SYS_COPYAREA is not set | ||
833 | # CONFIG_FB_SYS_IMAGEBLIT is not set | ||
834 | # CONFIG_FB_FOREIGN_ENDIAN is not set | ||
835 | # CONFIG_FB_SYS_FOPS is not set | ||
836 | # CONFIG_FB_SVGALIB is not set | ||
837 | # CONFIG_FB_MACMODES is not set | ||
838 | # CONFIG_FB_BACKLIGHT is not set | ||
839 | # CONFIG_FB_MODE_HELPERS is not set | ||
840 | # CONFIG_FB_TILEBLITTING is not set | ||
841 | |||
842 | # | ||
843 | # Frame buffer hardware drivers | ||
844 | # | ||
845 | # CONFIG_FB_S1D13XXX is not set | ||
846 | CONFIG_FB_ATMEL=y | ||
847 | # CONFIG_FB_VIRTUAL is not set | ||
848 | # CONFIG_FB_METRONOME is not set | ||
849 | # CONFIG_FB_MB862XX is not set | ||
850 | # CONFIG_FB_BROADSHEET is not set | ||
851 | CONFIG_BACKLIGHT_LCD_SUPPORT=y | ||
852 | CONFIG_LCD_CLASS_DEVICE=y | ||
853 | # CONFIG_LCD_LTV350QV is not set | ||
854 | # CONFIG_LCD_ILI9320 is not set | ||
855 | # CONFIG_LCD_TDO24M is not set | ||
856 | # CONFIG_LCD_VGG2432A4 is not set | ||
857 | # CONFIG_LCD_PLATFORM is not set | ||
858 | CONFIG_BACKLIGHT_CLASS_DEVICE=y | ||
859 | # CONFIG_BACKLIGHT_ATMEL_LCDC is not set | ||
860 | # CONFIG_BACKLIGHT_ATMEL_PWM is not set | ||
861 | CONFIG_BACKLIGHT_GENERIC=y | ||
862 | |||
863 | # | ||
864 | # Display device support | ||
865 | # | ||
866 | # CONFIG_DISPLAY_SUPPORT is not set | ||
867 | |||
868 | # | ||
869 | # Console display driver support | ||
870 | # | ||
871 | CONFIG_DUMMY_CONSOLE=y | ||
872 | # CONFIG_FRAMEBUFFER_CONSOLE is not set | ||
873 | # CONFIG_LOGO is not set | ||
874 | CONFIG_SOUND=m | ||
875 | CONFIG_SOUND_OSS_CORE=y | ||
876 | CONFIG_SND=m | ||
877 | CONFIG_SND_TIMER=m | ||
878 | CONFIG_SND_PCM=m | ||
879 | # CONFIG_SND_SEQUENCER is not set | ||
880 | CONFIG_SND_OSSEMUL=y | ||
881 | CONFIG_SND_MIXER_OSS=m | ||
882 | CONFIG_SND_PCM_OSS=m | ||
883 | CONFIG_SND_PCM_OSS_PLUGINS=y | ||
884 | # CONFIG_SND_DYNAMIC_MINORS is not set | ||
885 | # CONFIG_SND_SUPPORT_OLD_API is not set | ||
886 | # CONFIG_SND_VERBOSE_PROCFS is not set | ||
887 | # CONFIG_SND_VERBOSE_PRINTK is not set | ||
888 | # CONFIG_SND_DEBUG is not set | ||
889 | CONFIG_SND_VMASTER=y | ||
890 | CONFIG_SND_AC97_CODEC=m | ||
891 | CONFIG_SND_DRIVERS=y | ||
892 | # CONFIG_SND_DUMMY is not set | ||
893 | # CONFIG_SND_MTPAV is not set | ||
894 | # CONFIG_SND_SERIAL_U16550 is not set | ||
895 | # CONFIG_SND_MPU401 is not set | ||
896 | # CONFIG_SND_AC97_POWER_SAVE is not set | ||
897 | |||
898 | # | ||
899 | # Atmel devices (AVR32 and AT91) | ||
900 | # | ||
901 | # CONFIG_SND_ATMEL_ABDAC is not set | ||
902 | CONFIG_SND_ATMEL_AC97C=m | ||
903 | # CONFIG_SND_SPI is not set | ||
904 | # CONFIG_SND_SOC is not set | ||
905 | # CONFIG_SOUND_PRIME is not set | ||
906 | CONFIG_AC97_BUS=m | ||
907 | CONFIG_HID_SUPPORT=y | ||
908 | CONFIG_HID=y | ||
909 | # CONFIG_HID_DEBUG is not set | ||
910 | # CONFIG_HIDRAW is not set | ||
911 | # CONFIG_HID_PID is not set | ||
912 | |||
913 | # | ||
914 | # Special HID drivers | ||
915 | # | ||
916 | # CONFIG_HID_APPLE is not set | ||
917 | CONFIG_USB_SUPPORT=y | ||
918 | # CONFIG_USB_ARCH_HAS_HCD is not set | ||
919 | # CONFIG_USB_ARCH_HAS_OHCI is not set | ||
920 | # CONFIG_USB_ARCH_HAS_EHCI is not set | ||
921 | # CONFIG_USB_OTG_WHITELIST is not set | ||
922 | # CONFIG_USB_OTG_BLACKLIST_HUB is not set | ||
923 | # CONFIG_USB_MUSB_HDRC is not set | ||
924 | # CONFIG_USB_GADGET_MUSB_HDRC is not set | ||
925 | |||
926 | # | ||
927 | # NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may | ||
928 | # | ||
929 | CONFIG_USB_GADGET=m | ||
930 | # CONFIG_USB_GADGET_DEBUG is not set | ||
931 | CONFIG_USB_GADGET_DEBUG_FILES=y | ||
932 | # CONFIG_USB_GADGET_DEBUG_FS is not set | ||
933 | CONFIG_USB_GADGET_VBUS_DRAW=2 | ||
934 | CONFIG_USB_GADGET_SELECTED=y | ||
935 | # CONFIG_USB_GADGET_AT91 is not set | ||
936 | CONFIG_USB_GADGET_ATMEL_USBA=y | ||
937 | CONFIG_USB_ATMEL_USBA=m | ||
938 | # CONFIG_USB_GADGET_FSL_USB2 is not set | ||
939 | # CONFIG_USB_GADGET_LH7A40X is not set | ||
940 | # CONFIG_USB_GADGET_OMAP is not set | ||
941 | # CONFIG_USB_GADGET_PXA25X is not set | ||
942 | # CONFIG_USB_GADGET_PXA27X is not set | ||
943 | # CONFIG_USB_GADGET_S3C2410 is not set | ||
944 | # CONFIG_USB_GADGET_IMX is not set | ||
945 | # CONFIG_USB_GADGET_M66592 is not set | ||
946 | # CONFIG_USB_GADGET_AMD5536UDC is not set | ||
947 | # CONFIG_USB_GADGET_FSL_QE is not set | ||
948 | # CONFIG_USB_GADGET_CI13XXX is not set | ||
949 | # CONFIG_USB_GADGET_NET2280 is not set | ||
950 | # CONFIG_USB_GADGET_GOKU is not set | ||
951 | # CONFIG_USB_GADGET_DUMMY_HCD is not set | ||
952 | CONFIG_USB_GADGET_DUALSPEED=y | ||
953 | # CONFIG_USB_ZERO is not set | ||
954 | # CONFIG_USB_ETH is not set | ||
955 | # CONFIG_USB_GADGETFS is not set | ||
956 | CONFIG_USB_FILE_STORAGE=m | ||
957 | # CONFIG_USB_FILE_STORAGE_TEST is not set | ||
958 | CONFIG_USB_G_SERIAL=m | ||
959 | # CONFIG_USB_MIDI_GADGET is not set | ||
960 | # CONFIG_USB_G_PRINTER is not set | ||
961 | # CONFIG_USB_CDC_COMPOSITE is not set | ||
962 | |||
963 | # | ||
964 | # OTG and related infrastructure | ||
965 | # | ||
966 | # CONFIG_USB_GPIO_VBUS is not set | ||
967 | # CONFIG_NOP_USB_XCEIV is not set | ||
968 | CONFIG_MMC=y | ||
969 | # CONFIG_MMC_DEBUG is not set | ||
970 | # CONFIG_MMC_UNSAFE_RESUME is not set | ||
971 | |||
972 | # | ||
973 | # MMC/SD/SDIO Card Drivers | ||
974 | # | ||
975 | CONFIG_MMC_BLOCK=y | ||
976 | CONFIG_MMC_BLOCK_BOUNCE=y | ||
977 | # CONFIG_SDIO_UART is not set | ||
978 | # CONFIG_MMC_TEST is not set | ||
979 | |||
980 | # | ||
981 | # MMC/SD/SDIO Host Controller Drivers | ||
982 | # | ||
983 | # CONFIG_MMC_SDHCI is not set | ||
984 | CONFIG_MMC_ATMELMCI=y | ||
985 | # CONFIG_MMC_ATMELMCI_DMA is not set | ||
986 | # CONFIG_MMC_SPI is not set | ||
987 | # CONFIG_MEMSTICK is not set | ||
988 | CONFIG_NEW_LEDS=y | ||
989 | CONFIG_LEDS_CLASS=y | ||
990 | |||
991 | # | ||
992 | # LED drivers | ||
993 | # | ||
994 | CONFIG_LEDS_ATMEL_PWM=y | ||
995 | # CONFIG_LEDS_PCA9532 is not set | ||
996 | CONFIG_LEDS_GPIO=y | ||
997 | CONFIG_LEDS_GPIO_PLATFORM=y | ||
998 | # CONFIG_LEDS_LP5521 is not set | ||
999 | # CONFIG_LEDS_PCA955X is not set | ||
1000 | # CONFIG_LEDS_DAC124S085 is not set | ||
1001 | # CONFIG_LEDS_BD2802 is not set | ||
1002 | |||
1003 | # | ||
1004 | # LED Triggers | ||
1005 | # | ||
1006 | CONFIG_LEDS_TRIGGERS=y | ||
1007 | CONFIG_LEDS_TRIGGER_TIMER=y | ||
1008 | CONFIG_LEDS_TRIGGER_HEARTBEAT=y | ||
1009 | # CONFIG_LEDS_TRIGGER_BACKLIGHT is not set | ||
1010 | # CONFIG_LEDS_TRIGGER_GPIO is not set | ||
1011 | # CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set | ||
1012 | |||
1013 | # | ||
1014 | # iptables trigger is under Netfilter config (LED target) | ||
1015 | # | ||
1016 | # CONFIG_ACCESSIBILITY is not set | ||
1017 | CONFIG_RTC_LIB=m | ||
1018 | CONFIG_RTC_CLASS=m | ||
1019 | |||
1020 | # | ||
1021 | # RTC interfaces | ||
1022 | # | ||
1023 | CONFIG_RTC_INTF_SYSFS=y | ||
1024 | CONFIG_RTC_INTF_PROC=y | ||
1025 | CONFIG_RTC_INTF_DEV=y | ||
1026 | # CONFIG_RTC_INTF_DEV_UIE_EMUL is not set | ||
1027 | # CONFIG_RTC_DRV_TEST is not set | ||
1028 | |||
1029 | # | ||
1030 | # I2C RTC drivers | ||
1031 | # | ||
1032 | # CONFIG_RTC_DRV_DS1307 is not set | ||
1033 | # CONFIG_RTC_DRV_DS1374 is not set | ||
1034 | # CONFIG_RTC_DRV_DS1672 is not set | ||
1035 | # CONFIG_RTC_DRV_MAX6900 is not set | ||
1036 | # CONFIG_RTC_DRV_RS5C372 is not set | ||
1037 | # CONFIG_RTC_DRV_ISL1208 is not set | ||
1038 | # CONFIG_RTC_DRV_X1205 is not set | ||
1039 | # CONFIG_RTC_DRV_PCF8563 is not set | ||
1040 | # CONFIG_RTC_DRV_PCF8583 is not set | ||
1041 | # CONFIG_RTC_DRV_M41T80 is not set | ||
1042 | CONFIG_RTC_DRV_S35390A=m | ||
1043 | # CONFIG_RTC_DRV_FM3130 is not set | ||
1044 | # CONFIG_RTC_DRV_RX8581 is not set | ||
1045 | |||
1046 | # | ||
1047 | # SPI RTC drivers | ||
1048 | # | ||
1049 | # CONFIG_RTC_DRV_M41T94 is not set | ||
1050 | # CONFIG_RTC_DRV_DS1305 is not set | ||
1051 | # CONFIG_RTC_DRV_DS1390 is not set | ||
1052 | # CONFIG_RTC_DRV_MAX6902 is not set | ||
1053 | # CONFIG_RTC_DRV_R9701 is not set | ||
1054 | # CONFIG_RTC_DRV_RS5C348 is not set | ||
1055 | # CONFIG_RTC_DRV_DS3234 is not set | ||
1056 | |||
1057 | # | ||
1058 | # Platform RTC drivers | ||
1059 | # | ||
1060 | # CONFIG_RTC_DRV_DS1286 is not set | ||
1061 | # CONFIG_RTC_DRV_DS1511 is not set | ||
1062 | # CONFIG_RTC_DRV_DS1553 is not set | ||
1063 | # CONFIG_RTC_DRV_DS1742 is not set | ||
1064 | # CONFIG_RTC_DRV_STK17TA8 is not set | ||
1065 | # CONFIG_RTC_DRV_M48T86 is not set | ||
1066 | # CONFIG_RTC_DRV_M48T35 is not set | ||
1067 | # CONFIG_RTC_DRV_M48T59 is not set | ||
1068 | # CONFIG_RTC_DRV_BQ4802 is not set | ||
1069 | # CONFIG_RTC_DRV_V3020 is not set | ||
1070 | |||
1071 | # | ||
1072 | # on-CPU RTC drivers | ||
1073 | # | ||
1074 | CONFIG_RTC_DRV_AT32AP700X=m | ||
1075 | CONFIG_DMADEVICES=y | ||
1076 | |||
1077 | # | ||
1078 | # DMA Devices | ||
1079 | # | ||
1080 | CONFIG_DW_DMAC=y | ||
1081 | CONFIG_DMA_ENGINE=y | ||
1082 | |||
1083 | # | ||
1084 | # DMA Clients | ||
1085 | # | ||
1086 | # CONFIG_NET_DMA is not set | ||
1087 | # CONFIG_ASYNC_TX_DMA is not set | ||
1088 | # CONFIG_DMATEST is not set | ||
1089 | # CONFIG_AUXDISPLAY is not set | ||
1090 | CONFIG_UIO=y | ||
1091 | # CONFIG_UIO_PDRV is not set | ||
1092 | # CONFIG_UIO_PDRV_GENIRQ is not set | ||
1093 | # CONFIG_UIO_SMX is not set | ||
1094 | # CONFIG_UIO_SERCOS3 is not set | ||
1095 | # CONFIG_STAGING is not set | ||
1096 | |||
1097 | # | ||
1098 | # File systems | ||
1099 | # | ||
1100 | CONFIG_EXT2_FS=y | ||
1101 | CONFIG_EXT2_FS_XATTR=y | ||
1102 | # CONFIG_EXT2_FS_POSIX_ACL is not set | ||
1103 | # CONFIG_EXT2_FS_SECURITY is not set | ||
1104 | # CONFIG_EXT2_FS_XIP is not set | ||
1105 | CONFIG_EXT3_FS=y | ||
1106 | # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set | ||
1107 | CONFIG_EXT3_FS_XATTR=y | ||
1108 | # CONFIG_EXT3_FS_POSIX_ACL is not set | ||
1109 | # CONFIG_EXT3_FS_SECURITY is not set | ||
1110 | # CONFIG_EXT4_FS is not set | ||
1111 | CONFIG_JBD=y | ||
1112 | # CONFIG_JBD_DEBUG is not set | ||
1113 | CONFIG_FS_MBCACHE=y | ||
1114 | # CONFIG_REISERFS_FS is not set | ||
1115 | # CONFIG_JFS_FS is not set | ||
1116 | # CONFIG_FS_POSIX_ACL is not set | ||
1117 | CONFIG_FILE_LOCKING=y | ||
1118 | # CONFIG_XFS_FS is not set | ||
1119 | # CONFIG_OCFS2_FS is not set | ||
1120 | # CONFIG_BTRFS_FS is not set | ||
1121 | # CONFIG_DNOTIFY is not set | ||
1122 | # CONFIG_INOTIFY is not set | ||
1123 | # CONFIG_QUOTA is not set | ||
1124 | # CONFIG_AUTOFS_FS is not set | ||
1125 | # CONFIG_AUTOFS4_FS is not set | ||
1126 | # CONFIG_FUSE_FS is not set | ||
1127 | |||
1128 | # | ||
1129 | # Caches | ||
1130 | # | ||
1131 | # CONFIG_FSCACHE is not set | ||
1132 | |||
1133 | # | ||
1134 | # CD-ROM/DVD Filesystems | ||
1135 | # | ||
1136 | # CONFIG_ISO9660_FS is not set | ||
1137 | # CONFIG_UDF_FS is not set | ||
1138 | |||
1139 | # | ||
1140 | # DOS/FAT/NT Filesystems | ||
1141 | # | ||
1142 | CONFIG_FAT_FS=y | ||
1143 | CONFIG_MSDOS_FS=y | ||
1144 | CONFIG_VFAT_FS=y | ||
1145 | CONFIG_FAT_DEFAULT_CODEPAGE=850 | ||
1146 | CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" | ||
1147 | CONFIG_NTFS_FS=m | ||
1148 | # CONFIG_NTFS_DEBUG is not set | ||
1149 | CONFIG_NTFS_RW=y | ||
1150 | |||
1151 | # | ||
1152 | # Pseudo filesystems | ||
1153 | # | ||
1154 | CONFIG_PROC_FS=y | ||
1155 | # CONFIG_PROC_KCORE is not set | ||
1156 | CONFIG_PROC_SYSCTL=y | ||
1157 | CONFIG_PROC_PAGE_MONITOR=y | ||
1158 | CONFIG_SYSFS=y | ||
1159 | CONFIG_TMPFS=y | ||
1160 | # CONFIG_TMPFS_POSIX_ACL is not set | ||
1161 | # CONFIG_HUGETLB_PAGE is not set | ||
1162 | CONFIG_CONFIGFS_FS=y | ||
1163 | CONFIG_MISC_FILESYSTEMS=y | ||
1164 | # CONFIG_ADFS_FS is not set | ||
1165 | # CONFIG_AFFS_FS is not set | ||
1166 | # CONFIG_HFS_FS is not set | ||
1167 | # CONFIG_HFSPLUS_FS is not set | ||
1168 | # CONFIG_BEFS_FS is not set | ||
1169 | # CONFIG_BFS_FS is not set | ||
1170 | # CONFIG_EFS_FS is not set | ||
1171 | CONFIG_JFFS2_FS=y | ||
1172 | CONFIG_JFFS2_FS_DEBUG=0 | ||
1173 | CONFIG_JFFS2_FS_WRITEBUFFER=y | ||
1174 | # CONFIG_JFFS2_FS_WBUF_VERIFY is not set | ||
1175 | # CONFIG_JFFS2_SUMMARY is not set | ||
1176 | # CONFIG_JFFS2_FS_XATTR is not set | ||
1177 | # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set | ||
1178 | CONFIG_JFFS2_ZLIB=y | ||
1179 | # CONFIG_JFFS2_LZO is not set | ||
1180 | CONFIG_JFFS2_RTIME=y | ||
1181 | # CONFIG_JFFS2_RUBIN is not set | ||
1182 | # CONFIG_CRAMFS is not set | ||
1183 | # CONFIG_SQUASHFS is not set | ||
1184 | # CONFIG_VXFS_FS is not set | ||
1185 | # CONFIG_MINIX_FS is not set | ||
1186 | # CONFIG_OMFS_FS is not set | ||
1187 | # CONFIG_HPFS_FS is not set | ||
1188 | # CONFIG_QNX4FS_FS is not set | ||
1189 | # CONFIG_ROMFS_FS is not set | ||
1190 | # CONFIG_SYSV_FS is not set | ||
1191 | # CONFIG_UFS_FS is not set | ||
1192 | # CONFIG_NILFS2_FS is not set | ||
1193 | CONFIG_NETWORK_FILESYSTEMS=y | ||
1194 | CONFIG_NFS_FS=y | ||
1195 | CONFIG_NFS_V3=y | ||
1196 | # CONFIG_NFS_V3_ACL is not set | ||
1197 | # CONFIG_NFS_V4 is not set | ||
1198 | CONFIG_ROOT_NFS=y | ||
1199 | # CONFIG_NFSD is not set | ||
1200 | CONFIG_LOCKD=y | ||
1201 | CONFIG_LOCKD_V4=y | ||
1202 | CONFIG_NFS_COMMON=y | ||
1203 | CONFIG_SUNRPC=y | ||
1204 | # CONFIG_RPCSEC_GSS_KRB5 is not set | ||
1205 | # CONFIG_RPCSEC_GSS_SPKM3 is not set | ||
1206 | CONFIG_SMB_FS=m | ||
1207 | CONFIG_SMB_NLS_DEFAULT=y | ||
1208 | CONFIG_SMB_NLS_REMOTE="cp437" | ||
1209 | CONFIG_CIFS=m | ||
1210 | CONFIG_CIFS_STATS=y | ||
1211 | # CONFIG_CIFS_STATS2 is not set | ||
1212 | CONFIG_CIFS_WEAK_PW_HASH=y | ||
1213 | CONFIG_CIFS_XATTR=y | ||
1214 | CONFIG_CIFS_POSIX=y | ||
1215 | # CONFIG_CIFS_DEBUG2 is not set | ||
1216 | # CONFIG_CIFS_EXPERIMENTAL is not set | ||
1217 | # CONFIG_NCP_FS is not set | ||
1218 | # CONFIG_CODA_FS is not set | ||
1219 | # CONFIG_AFS_FS is not set | ||
1220 | |||
1221 | # | ||
1222 | # Partition Types | ||
1223 | # | ||
1224 | # CONFIG_PARTITION_ADVANCED is not set | ||
1225 | CONFIG_MSDOS_PARTITION=y | ||
1226 | CONFIG_NLS=y | ||
1227 | CONFIG_NLS_DEFAULT="iso8859-1" | ||
1228 | CONFIG_NLS_CODEPAGE_437=y | ||
1229 | # CONFIG_NLS_CODEPAGE_737 is not set | ||
1230 | # CONFIG_NLS_CODEPAGE_775 is not set | ||
1231 | CONFIG_NLS_CODEPAGE_850=y | ||
1232 | # CONFIG_NLS_CODEPAGE_852 is not set | ||
1233 | # CONFIG_NLS_CODEPAGE_855 is not set | ||
1234 | # CONFIG_NLS_CODEPAGE_857 is not set | ||
1235 | # CONFIG_NLS_CODEPAGE_860 is not set | ||
1236 | # CONFIG_NLS_CODEPAGE_861 is not set | ||
1237 | # CONFIG_NLS_CODEPAGE_862 is not set | ||
1238 | # CONFIG_NLS_CODEPAGE_863 is not set | ||
1239 | # CONFIG_NLS_CODEPAGE_864 is not set | ||
1240 | # CONFIG_NLS_CODEPAGE_865 is not set | ||
1241 | # CONFIG_NLS_CODEPAGE_866 is not set | ||
1242 | # CONFIG_NLS_CODEPAGE_869 is not set | ||
1243 | # CONFIG_NLS_CODEPAGE_936 is not set | ||
1244 | # CONFIG_NLS_CODEPAGE_950 is not set | ||
1245 | # CONFIG_NLS_CODEPAGE_932 is not set | ||
1246 | # CONFIG_NLS_CODEPAGE_949 is not set | ||
1247 | # CONFIG_NLS_CODEPAGE_874 is not set | ||
1248 | # CONFIG_NLS_ISO8859_8 is not set | ||
1249 | # CONFIG_NLS_CODEPAGE_1250 is not set | ||
1250 | # CONFIG_NLS_CODEPAGE_1251 is not set | ||
1251 | # CONFIG_NLS_ASCII is not set | ||
1252 | CONFIG_NLS_ISO8859_1=y | ||
1253 | # CONFIG_NLS_ISO8859_2 is not set | ||
1254 | # CONFIG_NLS_ISO8859_3 is not set | ||
1255 | # CONFIG_NLS_ISO8859_4 is not set | ||
1256 | # CONFIG_NLS_ISO8859_5 is not set | ||
1257 | # CONFIG_NLS_ISO8859_6 is not set | ||
1258 | # CONFIG_NLS_ISO8859_7 is not set | ||
1259 | # CONFIG_NLS_ISO8859_9 is not set | ||
1260 | # CONFIG_NLS_ISO8859_13 is not set | ||
1261 | # CONFIG_NLS_ISO8859_14 is not set | ||
1262 | # CONFIG_NLS_ISO8859_15 is not set | ||
1263 | # CONFIG_NLS_KOI8_R is not set | ||
1264 | # CONFIG_NLS_KOI8_U is not set | ||
1265 | CONFIG_NLS_UTF8=y | ||
1266 | # CONFIG_DLM is not set | ||
1267 | |||
1268 | # | ||
1269 | # Kernel hacking | ||
1270 | # | ||
1271 | # CONFIG_PRINTK_TIME is not set | ||
1272 | CONFIG_ENABLE_WARN_DEPRECATED=y | ||
1273 | CONFIG_ENABLE_MUST_CHECK=y | ||
1274 | CONFIG_FRAME_WARN=1024 | ||
1275 | CONFIG_MAGIC_SYSRQ=y | ||
1276 | # CONFIG_UNUSED_SYMBOLS is not set | ||
1277 | CONFIG_DEBUG_FS=y | ||
1278 | # CONFIG_HEADERS_CHECK is not set | ||
1279 | CONFIG_DEBUG_KERNEL=y | ||
1280 | # CONFIG_DEBUG_SHIRQ is not set | ||
1281 | CONFIG_DETECT_SOFTLOCKUP=y | ||
1282 | # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set | ||
1283 | CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 | ||
1284 | CONFIG_DETECT_HUNG_TASK=y | ||
1285 | # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set | ||
1286 | CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 | ||
1287 | CONFIG_SCHED_DEBUG=y | ||
1288 | # CONFIG_SCHEDSTATS is not set | ||
1289 | # CONFIG_TIMER_STATS is not set | ||
1290 | # CONFIG_DEBUG_OBJECTS is not set | ||
1291 | # CONFIG_DEBUG_RT_MUTEXES is not set | ||
1292 | # CONFIG_RT_MUTEX_TESTER is not set | ||
1293 | # CONFIG_DEBUG_SPINLOCK is not set | ||
1294 | # CONFIG_DEBUG_MUTEXES is not set | ||
1295 | # CONFIG_DEBUG_LOCK_ALLOC is not set | ||
1296 | # CONFIG_PROVE_LOCKING is not set | ||
1297 | # CONFIG_LOCK_STAT is not set | ||
1298 | # CONFIG_DEBUG_SPINLOCK_SLEEP is not set | ||
1299 | # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set | ||
1300 | # CONFIG_DEBUG_KOBJECT is not set | ||
1301 | CONFIG_DEBUG_BUGVERBOSE=y | ||
1302 | # CONFIG_DEBUG_INFO is not set | ||
1303 | # CONFIG_DEBUG_VM is not set | ||
1304 | # CONFIG_DEBUG_WRITECOUNT is not set | ||
1305 | # CONFIG_DEBUG_MEMORY_INIT is not set | ||
1306 | # CONFIG_DEBUG_LIST is not set | ||
1307 | # CONFIG_DEBUG_SG is not set | ||
1308 | # CONFIG_DEBUG_NOTIFIERS is not set | ||
1309 | CONFIG_FRAME_POINTER=y | ||
1310 | # CONFIG_BOOT_PRINTK_DELAY is not set | ||
1311 | # CONFIG_RCU_TORTURE_TEST is not set | ||
1312 | # CONFIG_RCU_CPU_STALL_DETECTOR is not set | ||
1313 | # CONFIG_BACKTRACE_SELF_TEST is not set | ||
1314 | # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set | ||
1315 | # CONFIG_FAULT_INJECTION is not set | ||
1316 | # CONFIG_PAGE_POISONING is not set | ||
1317 | CONFIG_TRACING_SUPPORT=y | ||
1318 | |||
1319 | # | ||
1320 | # Tracers | ||
1321 | # | ||
1322 | # CONFIG_IRQSOFF_TRACER is not set | ||
1323 | # CONFIG_SCHED_TRACER is not set | ||
1324 | # CONFIG_CONTEXT_SWITCH_TRACER is not set | ||
1325 | # CONFIG_EVENT_TRACER is not set | ||
1326 | # CONFIG_BOOT_TRACER is not set | ||
1327 | # CONFIG_TRACE_BRANCH_PROFILING is not set | ||
1328 | # CONFIG_KMEMTRACE is not set | ||
1329 | # CONFIG_WORKQUEUE_TRACER is not set | ||
1330 | # CONFIG_BLK_DEV_IO_TRACE is not set | ||
1331 | # CONFIG_DYNAMIC_DEBUG is not set | ||
1332 | # CONFIG_SAMPLES is not set | ||
1333 | |||
1334 | # | ||
1335 | # Security options | ||
1336 | # | ||
1337 | # CONFIG_KEYS is not set | ||
1338 | # CONFIG_SECURITY is not set | ||
1339 | # CONFIG_SECURITYFS is not set | ||
1340 | # CONFIG_SECURITY_FILE_CAPABILITIES is not set | ||
1341 | # CONFIG_CRYPTO is not set | ||
1342 | # CONFIG_BINARY_PRINTF is not set | ||
1343 | |||
1344 | # | ||
1345 | # Library routines | ||
1346 | # | ||
1347 | CONFIG_BITREVERSE=y | ||
1348 | CONFIG_GENERIC_FIND_LAST_BIT=y | ||
1349 | CONFIG_CRC_CCITT=y | ||
1350 | # CONFIG_CRC16 is not set | ||
1351 | # CONFIG_CRC_T10DIF is not set | ||
1352 | # CONFIG_CRC_ITU_T is not set | ||
1353 | CONFIG_CRC32=y | ||
1354 | # CONFIG_CRC7 is not set | ||
1355 | # CONFIG_LIBCRC32C is not set | ||
1356 | CONFIG_ZLIB_INFLATE=y | ||
1357 | CONFIG_ZLIB_DEFLATE=y | ||
1358 | CONFIG_DECOMPRESS_GZIP=y | ||
1359 | CONFIG_GENERIC_ALLOCATOR=y | ||
1360 | CONFIG_HAS_IOMEM=y | ||
1361 | CONFIG_HAS_IOPORT=y | ||
1362 | CONFIG_HAS_DMA=y | ||
1363 | CONFIG_NLATTR=y | ||
diff --git a/arch/avr32/include/asm/hw_irq.h b/arch/avr32/include/asm/hw_irq.h index 218b0a6bfd1b..a36f9fcb8fcd 100644 --- a/arch/avr32/include/asm/hw_irq.h +++ b/arch/avr32/include/asm/hw_irq.h | |||
@@ -1,7 +1,7 @@ | |||
1 | #ifndef __ASM_AVR32_HW_IRQ_H | 1 | #ifndef __ASM_AVR32_HW_IRQ_H |
2 | #define __ASM_AVR32_HW_IRQ_H | 2 | #define __ASM_AVR32_HW_IRQ_H |
3 | 3 | ||
4 | static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) | 4 | static inline void hw_resend_irq(struct irq_chip *h, unsigned int i) |
5 | { | 5 | { |
6 | /* Nothing to do */ | 6 | /* Nothing to do */ |
7 | } | 7 | } |
diff --git a/arch/avr32/kernel/traps.c b/arch/avr32/kernel/traps.c index d547c8df157d..6e3d491184ea 100644 --- a/arch/avr32/kernel/traps.c +++ b/arch/avr32/kernel/traps.c | |||
@@ -75,8 +75,17 @@ void _exception(long signr, struct pt_regs *regs, int code, | |||
75 | { | 75 | { |
76 | siginfo_t info; | 76 | siginfo_t info; |
77 | 77 | ||
78 | if (!user_mode(regs)) | 78 | if (!user_mode(regs)) { |
79 | const struct exception_table_entry *fixup; | ||
80 | |||
81 | /* Are we prepared to handle this kernel fault? */ | ||
82 | fixup = search_exception_tables(regs->pc); | ||
83 | if (fixup) { | ||
84 | regs->pc = fixup->fixup; | ||
85 | return; | ||
86 | } | ||
79 | die("Unhandled exception in kernel mode", regs, signr); | 87 | die("Unhandled exception in kernel mode", regs, signr); |
88 | } | ||
80 | 89 | ||
81 | memset(&info, 0, sizeof(info)); | 90 | memset(&info, 0, sizeof(info)); |
82 | info.si_signo = signr; | 91 | info.si_signo = signr; |
diff --git a/arch/avr32/mach-at32ap/include/mach/board.h b/arch/avr32/mach-at32ap/include/mach/board.h index 0b8164281899..ddedb471f33e 100644 --- a/arch/avr32/mach-at32ap/include/mach/board.h +++ b/arch/avr32/mach-at32ap/include/mach/board.h | |||
@@ -29,7 +29,7 @@ extern struct platform_device *atmel_default_console_device; | |||
29 | /* Flags for selecting USART extra pins */ | 29 | /* Flags for selecting USART extra pins */ |
30 | #define ATMEL_USART_RTS 0x01 | 30 | #define ATMEL_USART_RTS 0x01 |
31 | #define ATMEL_USART_CTS 0x02 | 31 | #define ATMEL_USART_CTS 0x02 |
32 | #define ATMEL_USART_CLK 0x03 | 32 | #define ATMEL_USART_CLK 0x04 |
33 | 33 | ||
34 | struct atmel_uart_data { | 34 | struct atmel_uart_data { |
35 | short use_dma_tx; /* use transmit DMA? */ | 35 | short use_dma_tx; /* use transmit DMA? */ |
diff --git a/arch/frv/include/asm/signal.h b/arch/frv/include/asm/signal.h index 2079197d483d..f071e813dcb3 100644 --- a/arch/frv/include/asm/signal.h +++ b/arch/frv/include/asm/signal.h | |||
@@ -3,107 +3,15 @@ | |||
3 | 3 | ||
4 | #include <linux/types.h> | 4 | #include <linux/types.h> |
5 | 5 | ||
6 | /* Avoid too many header ordering problems. */ | 6 | #ifndef __KERNEL__ |
7 | struct siginfo; | ||
8 | |||
9 | #ifdef __KERNEL__ | ||
10 | /* Most things should be clean enough to redefine this at will, if care | ||
11 | is taken to make libc match. */ | ||
12 | |||
13 | #define _NSIG 64 | ||
14 | #define _NSIG_BPW 32 | ||
15 | #define _NSIG_WORDS (_NSIG / _NSIG_BPW) | ||
16 | |||
17 | typedef unsigned long old_sigset_t; /* at least 32 bits */ | ||
18 | |||
19 | typedef struct { | ||
20 | unsigned long sig[_NSIG_WORDS]; | ||
21 | } sigset_t; | ||
22 | |||
23 | #else | ||
24 | /* Here we must cater to libcs that poke about in kernel headers. */ | 7 | /* Here we must cater to libcs that poke about in kernel headers. */ |
25 | 8 | ||
26 | #define NSIG 32 | 9 | #define NSIG 32 |
27 | typedef unsigned long sigset_t; | 10 | typedef unsigned long sigset_t; |
28 | 11 | ||
29 | #endif /* __KERNEL__ */ | 12 | #endif /* !__KERNEL__ */ |
30 | |||
31 | #define SIGHUP 1 | ||
32 | #define SIGINT 2 | ||
33 | #define SIGQUIT 3 | ||
34 | #define SIGILL 4 | ||
35 | #define SIGTRAP 5 | ||
36 | #define SIGABRT 6 | ||
37 | #define SIGIOT 6 | ||
38 | #define SIGBUS 7 | ||
39 | #define SIGFPE 8 | ||
40 | #define SIGKILL 9 | ||
41 | #define SIGUSR1 10 | ||
42 | #define SIGSEGV 11 | ||
43 | #define SIGUSR2 12 | ||
44 | #define SIGPIPE 13 | ||
45 | #define SIGALRM 14 | ||
46 | #define SIGTERM 15 | ||
47 | #define SIGSTKFLT 16 | ||
48 | #define SIGCHLD 17 | ||
49 | #define SIGCONT 18 | ||
50 | #define SIGSTOP 19 | ||
51 | #define SIGTSTP 20 | ||
52 | #define SIGTTIN 21 | ||
53 | #define SIGTTOU 22 | ||
54 | #define SIGURG 23 | ||
55 | #define SIGXCPU 24 | ||
56 | #define SIGXFSZ 25 | ||
57 | #define SIGVTALRM 26 | ||
58 | #define SIGPROF 27 | ||
59 | #define SIGWINCH 28 | ||
60 | #define SIGIO 29 | ||
61 | #define SIGPOLL SIGIO | ||
62 | /* | ||
63 | #define SIGLOST 29 | ||
64 | */ | ||
65 | #define SIGPWR 30 | ||
66 | #define SIGSYS 31 | ||
67 | #define SIGUNUSED 31 | ||
68 | |||
69 | /* These should not be considered constants from userland. */ | ||
70 | #define SIGRTMIN 32 | ||
71 | #define SIGRTMAX (_NSIG-1) | ||
72 | |||
73 | /* | ||
74 | * SA_FLAGS values: | ||
75 | * | ||
76 | * SA_ONSTACK indicates that a registered stack_t will be used. | ||
77 | * SA_RESTART flag to get restarting signals (which were the default long ago) | ||
78 | * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. | ||
79 | * SA_RESETHAND clears the handler when the signal is delivered. | ||
80 | * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. | ||
81 | * SA_NODEFER prevents the current signal from being masked in the handler. | ||
82 | * | ||
83 | * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single | ||
84 | * Unix names RESETHAND and NODEFER respectively. | ||
85 | */ | ||
86 | #define SA_NOCLDSTOP 0x00000001 | ||
87 | #define SA_NOCLDWAIT 0x00000002 /* not supported yet */ | ||
88 | #define SA_SIGINFO 0x00000004 | ||
89 | #define SA_ONSTACK 0x08000000 | ||
90 | #define SA_RESTART 0x10000000 | ||
91 | #define SA_NODEFER 0x40000000 | ||
92 | #define SA_RESETHAND 0x80000000 | ||
93 | |||
94 | #define SA_NOMASK SA_NODEFER | ||
95 | #define SA_ONESHOT SA_RESETHAND | ||
96 | |||
97 | #define SA_RESTORER 0x04000000 | ||
98 | |||
99 | /* | ||
100 | * sigaltstack controls | ||
101 | */ | ||
102 | #define SS_ONSTACK 1 | ||
103 | #define SS_DISABLE 2 | ||
104 | 13 | ||
105 | #define MINSIGSTKSZ 2048 | 14 | #define SA_RESTORER 0x04000000 /* to get struct sigaction correct */ |
106 | #define SIGSTKSZ 8192 | ||
107 | 15 | ||
108 | #include <asm-generic/signal.h> | 16 | #include <asm-generic/signal.h> |
109 | 17 | ||
@@ -115,16 +23,6 @@ struct old_sigaction { | |||
115 | __sigrestore_t sa_restorer; | 23 | __sigrestore_t sa_restorer; |
116 | }; | 24 | }; |
117 | 25 | ||
118 | struct sigaction { | ||
119 | __sighandler_t sa_handler; | ||
120 | unsigned long sa_flags; | ||
121 | __sigrestore_t sa_restorer; | ||
122 | sigset_t sa_mask; /* mask last for extensibility */ | ||
123 | }; | ||
124 | |||
125 | struct k_sigaction { | ||
126 | struct sigaction sa; | ||
127 | }; | ||
128 | #else | 26 | #else |
129 | /* Here we must cater to libcs that poke about in kernel headers. */ | 27 | /* Here we must cater to libcs that poke about in kernel headers. */ |
130 | 28 | ||
@@ -143,19 +41,4 @@ struct sigaction { | |||
143 | 41 | ||
144 | #endif /* __KERNEL__ */ | 42 | #endif /* __KERNEL__ */ |
145 | 43 | ||
146 | typedef struct sigaltstack { | ||
147 | void __user *ss_sp; | ||
148 | int ss_flags; | ||
149 | size_t ss_size; | ||
150 | } stack_t; | ||
151 | |||
152 | #define ptrace_signal_deliver(regs, cookie) do { } while (0) | ||
153 | |||
154 | #ifdef __KERNEL__ | ||
155 | |||
156 | #include <asm/sigcontext.h> | ||
157 | #undef __HAVE_ARCH_SIG_BITOPS | ||
158 | |||
159 | #endif /* __KERNEL__ */ | ||
160 | |||
161 | #endif /* _ASM_SIGNAL_H */ | 44 | #endif /* _ASM_SIGNAL_H */ |
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 68f5578fe38e..356d2ec8e2fb 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -789,10 +789,26 @@ config X86_MCE | |||
789 | to disable it. MCE support simply ignores non-MCE processors like | 789 | to disable it. MCE support simply ignores non-MCE processors like |
790 | the 386 and 486, so nearly everyone can say Y here. | 790 | the 386 and 486, so nearly everyone can say Y here. |
791 | 791 | ||
792 | config X86_OLD_MCE | ||
793 | depends on X86_32 && X86_MCE | ||
794 | bool "Use legacy machine check code (will go away)" | ||
795 | default n | ||
796 | select X86_ANCIENT_MCE | ||
797 | ---help--- | ||
798 | Use the old i386 machine check code. This is merely intended for | ||
799 | testing in a transition period. Try this if you run into any machine | ||
800 | check related software problems, but report the problem to | ||
801 | linux-kernel. When in doubt say no. | ||
802 | |||
803 | config X86_NEW_MCE | ||
804 | depends on X86_MCE | ||
805 | bool | ||
806 | default y if (!X86_OLD_MCE && X86_32) || X86_64 | ||
807 | |||
792 | config X86_MCE_INTEL | 808 | config X86_MCE_INTEL |
793 | def_bool y | 809 | def_bool y |
794 | prompt "Intel MCE features" | 810 | prompt "Intel MCE features" |
795 | depends on X86_64 && X86_MCE && X86_LOCAL_APIC | 811 | depends on X86_NEW_MCE && X86_LOCAL_APIC |
796 | ---help--- | 812 | ---help--- |
797 | Additional support for intel specific MCE features such as | 813 | Additional support for intel specific MCE features such as |
798 | the thermal monitor. | 814 | the thermal monitor. |
@@ -800,19 +816,36 @@ config X86_MCE_INTEL | |||
800 | config X86_MCE_AMD | 816 | config X86_MCE_AMD |
801 | def_bool y | 817 | def_bool y |
802 | prompt "AMD MCE features" | 818 | prompt "AMD MCE features" |
803 | depends on X86_64 && X86_MCE && X86_LOCAL_APIC | 819 | depends on X86_NEW_MCE && X86_LOCAL_APIC |
804 | ---help--- | 820 | ---help--- |
805 | Additional support for AMD specific MCE features such as | 821 | Additional support for AMD specific MCE features such as |
806 | the DRAM Error Threshold. | 822 | the DRAM Error Threshold. |
807 | 823 | ||
824 | config X86_ANCIENT_MCE | ||
825 | def_bool n | ||
826 | depends on X86_32 | ||
827 | prompt "Support for old Pentium 5 / WinChip machine checks" | ||
828 | ---help--- | ||
829 | Include support for machine check handling on old Pentium 5 or WinChip | ||
830 | systems. These typically need to be enabled explicitely on the command | ||
831 | line. | ||
832 | |||
808 | config X86_MCE_THRESHOLD | 833 | config X86_MCE_THRESHOLD |
809 | depends on X86_MCE_AMD || X86_MCE_INTEL | 834 | depends on X86_MCE_AMD || X86_MCE_INTEL |
810 | bool | 835 | bool |
811 | default y | 836 | default y |
812 | 837 | ||
838 | config X86_MCE_INJECT | ||
839 | depends on X86_NEW_MCE | ||
840 | tristate "Machine check injector support" | ||
841 | ---help--- | ||
842 | Provide support for injecting machine checks for testing purposes. | ||
843 | If you don't know what a machine check is and you don't do kernel | ||
844 | QA it is safe to say n. | ||
845 | |||
813 | config X86_MCE_NONFATAL | 846 | config X86_MCE_NONFATAL |
814 | tristate "Check for non-fatal errors on AMD Athlon/Duron / Intel Pentium 4" | 847 | tristate "Check for non-fatal errors on AMD Athlon/Duron / Intel Pentium 4" |
815 | depends on X86_32 && X86_MCE | 848 | depends on X86_OLD_MCE |
816 | ---help--- | 849 | ---help--- |
817 | Enabling this feature starts a timer that triggers every 5 seconds which | 850 | Enabling this feature starts a timer that triggers every 5 seconds which |
818 | will look at the machine check registers to see if anything happened. | 851 | will look at the machine check registers to see if anything happened. |
@@ -825,11 +858,15 @@ config X86_MCE_NONFATAL | |||
825 | 858 | ||
826 | config X86_MCE_P4THERMAL | 859 | config X86_MCE_P4THERMAL |
827 | bool "check for P4 thermal throttling interrupt." | 860 | bool "check for P4 thermal throttling interrupt." |
828 | depends on X86_32 && X86_MCE && (X86_UP_APIC || SMP) | 861 | depends on X86_OLD_MCE && X86_MCE && (X86_UP_APIC || SMP) |
829 | ---help--- | 862 | ---help--- |
830 | Enabling this feature will cause a message to be printed when the P4 | 863 | Enabling this feature will cause a message to be printed when the P4 |
831 | enters thermal throttling. | 864 | enters thermal throttling. |
832 | 865 | ||
866 | config X86_THERMAL_VECTOR | ||
867 | def_bool y | ||
868 | depends on X86_MCE_P4THERMAL || X86_MCE_INTEL | ||
869 | |||
833 | config VM86 | 870 | config VM86 |
834 | bool "Enable VM86 support" if EMBEDDED | 871 | bool "Enable VM86 support" if EMBEDDED |
835 | default y | 872 | default y |
diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile index ebe7deedd5b4..cfb0010fa940 100644 --- a/arch/x86/crypto/Makefile +++ b/arch/x86/crypto/Makefile | |||
@@ -2,6 +2,8 @@ | |||
2 | # Arch-specific CryptoAPI modules. | 2 | # Arch-specific CryptoAPI modules. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_CRYPTO_FPU) += fpu.o | ||
6 | |||
5 | obj-$(CONFIG_CRYPTO_AES_586) += aes-i586.o | 7 | obj-$(CONFIG_CRYPTO_AES_586) += aes-i586.o |
6 | obj-$(CONFIG_CRYPTO_TWOFISH_586) += twofish-i586.o | 8 | obj-$(CONFIG_CRYPTO_TWOFISH_586) += twofish-i586.o |
7 | obj-$(CONFIG_CRYPTO_SALSA20_586) += salsa20-i586.o | 9 | obj-$(CONFIG_CRYPTO_SALSA20_586) += salsa20-i586.o |
diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c index 02af0af65497..4e663398f77f 100644 --- a/arch/x86/crypto/aesni-intel_glue.c +++ b/arch/x86/crypto/aesni-intel_glue.c | |||
@@ -21,6 +21,22 @@ | |||
21 | #include <asm/i387.h> | 21 | #include <asm/i387.h> |
22 | #include <asm/aes.h> | 22 | #include <asm/aes.h> |
23 | 23 | ||
24 | #if defined(CONFIG_CRYPTO_CTR) || defined(CONFIG_CRYPTO_CTR_MODULE) | ||
25 | #define HAS_CTR | ||
26 | #endif | ||
27 | |||
28 | #if defined(CONFIG_CRYPTO_LRW) || defined(CONFIG_CRYPTO_LRW_MODULE) | ||
29 | #define HAS_LRW | ||
30 | #endif | ||
31 | |||
32 | #if defined(CONFIG_CRYPTO_PCBC) || defined(CONFIG_CRYPTO_PCBC_MODULE) | ||
33 | #define HAS_PCBC | ||
34 | #endif | ||
35 | |||
36 | #if defined(CONFIG_CRYPTO_XTS) || defined(CONFIG_CRYPTO_XTS_MODULE) | ||
37 | #define HAS_XTS | ||
38 | #endif | ||
39 | |||
24 | struct async_aes_ctx { | 40 | struct async_aes_ctx { |
25 | struct cryptd_ablkcipher *cryptd_tfm; | 41 | struct cryptd_ablkcipher *cryptd_tfm; |
26 | }; | 42 | }; |
@@ -137,6 +153,41 @@ static struct crypto_alg aesni_alg = { | |||
137 | } | 153 | } |
138 | }; | 154 | }; |
139 | 155 | ||
156 | static void __aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) | ||
157 | { | ||
158 | struct crypto_aes_ctx *ctx = aes_ctx(crypto_tfm_ctx(tfm)); | ||
159 | |||
160 | aesni_enc(ctx, dst, src); | ||
161 | } | ||
162 | |||
163 | static void __aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) | ||
164 | { | ||
165 | struct crypto_aes_ctx *ctx = aes_ctx(crypto_tfm_ctx(tfm)); | ||
166 | |||
167 | aesni_dec(ctx, dst, src); | ||
168 | } | ||
169 | |||
170 | static struct crypto_alg __aesni_alg = { | ||
171 | .cra_name = "__aes-aesni", | ||
172 | .cra_driver_name = "__driver-aes-aesni", | ||
173 | .cra_priority = 0, | ||
174 | .cra_flags = CRYPTO_ALG_TYPE_CIPHER, | ||
175 | .cra_blocksize = AES_BLOCK_SIZE, | ||
176 | .cra_ctxsize = sizeof(struct crypto_aes_ctx)+AESNI_ALIGN-1, | ||
177 | .cra_alignmask = 0, | ||
178 | .cra_module = THIS_MODULE, | ||
179 | .cra_list = LIST_HEAD_INIT(__aesni_alg.cra_list), | ||
180 | .cra_u = { | ||
181 | .cipher = { | ||
182 | .cia_min_keysize = AES_MIN_KEY_SIZE, | ||
183 | .cia_max_keysize = AES_MAX_KEY_SIZE, | ||
184 | .cia_setkey = aes_set_key, | ||
185 | .cia_encrypt = __aes_encrypt, | ||
186 | .cia_decrypt = __aes_decrypt | ||
187 | } | ||
188 | } | ||
189 | }; | ||
190 | |||
140 | static int ecb_encrypt(struct blkcipher_desc *desc, | 191 | static int ecb_encrypt(struct blkcipher_desc *desc, |
141 | struct scatterlist *dst, struct scatterlist *src, | 192 | struct scatterlist *dst, struct scatterlist *src, |
142 | unsigned int nbytes) | 193 | unsigned int nbytes) |
@@ -277,8 +328,16 @@ static int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key, | |||
277 | unsigned int key_len) | 328 | unsigned int key_len) |
278 | { | 329 | { |
279 | struct async_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm); | 330 | struct async_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm); |
331 | struct crypto_ablkcipher *child = &ctx->cryptd_tfm->base; | ||
332 | int err; | ||
280 | 333 | ||
281 | return crypto_ablkcipher_setkey(&ctx->cryptd_tfm->base, key, key_len); | 334 | crypto_ablkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); |
335 | crypto_ablkcipher_set_flags(child, crypto_ablkcipher_get_flags(tfm) | ||
336 | & CRYPTO_TFM_REQ_MASK); | ||
337 | err = crypto_ablkcipher_setkey(child, key, key_len); | ||
338 | crypto_ablkcipher_set_flags(tfm, crypto_ablkcipher_get_flags(child) | ||
339 | & CRYPTO_TFM_RES_MASK); | ||
340 | return err; | ||
282 | } | 341 | } |
283 | 342 | ||
284 | static int ablk_encrypt(struct ablkcipher_request *req) | 343 | static int ablk_encrypt(struct ablkcipher_request *req) |
@@ -411,6 +470,163 @@ static struct crypto_alg ablk_cbc_alg = { | |||
411 | }, | 470 | }, |
412 | }; | 471 | }; |
413 | 472 | ||
473 | #ifdef HAS_CTR | ||
474 | static int ablk_ctr_init(struct crypto_tfm *tfm) | ||
475 | { | ||
476 | struct cryptd_ablkcipher *cryptd_tfm; | ||
477 | |||
478 | cryptd_tfm = cryptd_alloc_ablkcipher("fpu(ctr(__driver-aes-aesni))", | ||
479 | 0, 0); | ||
480 | if (IS_ERR(cryptd_tfm)) | ||
481 | return PTR_ERR(cryptd_tfm); | ||
482 | ablk_init_common(tfm, cryptd_tfm); | ||
483 | return 0; | ||
484 | } | ||
485 | |||
486 | static struct crypto_alg ablk_ctr_alg = { | ||
487 | .cra_name = "ctr(aes)", | ||
488 | .cra_driver_name = "ctr-aes-aesni", | ||
489 | .cra_priority = 400, | ||
490 | .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC, | ||
491 | .cra_blocksize = 1, | ||
492 | .cra_ctxsize = sizeof(struct async_aes_ctx), | ||
493 | .cra_alignmask = 0, | ||
494 | .cra_type = &crypto_ablkcipher_type, | ||
495 | .cra_module = THIS_MODULE, | ||
496 | .cra_list = LIST_HEAD_INIT(ablk_ctr_alg.cra_list), | ||
497 | .cra_init = ablk_ctr_init, | ||
498 | .cra_exit = ablk_exit, | ||
499 | .cra_u = { | ||
500 | .ablkcipher = { | ||
501 | .min_keysize = AES_MIN_KEY_SIZE, | ||
502 | .max_keysize = AES_MAX_KEY_SIZE, | ||
503 | .ivsize = AES_BLOCK_SIZE, | ||
504 | .setkey = ablk_set_key, | ||
505 | .encrypt = ablk_encrypt, | ||
506 | .decrypt = ablk_decrypt, | ||
507 | .geniv = "chainiv", | ||
508 | }, | ||
509 | }, | ||
510 | }; | ||
511 | #endif | ||
512 | |||
513 | #ifdef HAS_LRW | ||
514 | static int ablk_lrw_init(struct crypto_tfm *tfm) | ||
515 | { | ||
516 | struct cryptd_ablkcipher *cryptd_tfm; | ||
517 | |||
518 | cryptd_tfm = cryptd_alloc_ablkcipher("fpu(lrw(__driver-aes-aesni))", | ||
519 | 0, 0); | ||
520 | if (IS_ERR(cryptd_tfm)) | ||
521 | return PTR_ERR(cryptd_tfm); | ||
522 | ablk_init_common(tfm, cryptd_tfm); | ||
523 | return 0; | ||
524 | } | ||
525 | |||
526 | static struct crypto_alg ablk_lrw_alg = { | ||
527 | .cra_name = "lrw(aes)", | ||
528 | .cra_driver_name = "lrw-aes-aesni", | ||
529 | .cra_priority = 400, | ||
530 | .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC, | ||
531 | .cra_blocksize = AES_BLOCK_SIZE, | ||
532 | .cra_ctxsize = sizeof(struct async_aes_ctx), | ||
533 | .cra_alignmask = 0, | ||
534 | .cra_type = &crypto_ablkcipher_type, | ||
535 | .cra_module = THIS_MODULE, | ||
536 | .cra_list = LIST_HEAD_INIT(ablk_lrw_alg.cra_list), | ||
537 | .cra_init = ablk_lrw_init, | ||
538 | .cra_exit = ablk_exit, | ||
539 | .cra_u = { | ||
540 | .ablkcipher = { | ||
541 | .min_keysize = AES_MIN_KEY_SIZE + AES_BLOCK_SIZE, | ||
542 | .max_keysize = AES_MAX_KEY_SIZE + AES_BLOCK_SIZE, | ||
543 | .ivsize = AES_BLOCK_SIZE, | ||
544 | .setkey = ablk_set_key, | ||
545 | .encrypt = ablk_encrypt, | ||
546 | .decrypt = ablk_decrypt, | ||
547 | }, | ||
548 | }, | ||
549 | }; | ||
550 | #endif | ||
551 | |||
552 | #ifdef HAS_PCBC | ||
553 | static int ablk_pcbc_init(struct crypto_tfm *tfm) | ||
554 | { | ||
555 | struct cryptd_ablkcipher *cryptd_tfm; | ||
556 | |||
557 | cryptd_tfm = cryptd_alloc_ablkcipher("fpu(pcbc(__driver-aes-aesni))", | ||
558 | 0, 0); | ||
559 | if (IS_ERR(cryptd_tfm)) | ||
560 | return PTR_ERR(cryptd_tfm); | ||
561 | ablk_init_common(tfm, cryptd_tfm); | ||
562 | return 0; | ||
563 | } | ||
564 | |||
565 | static struct crypto_alg ablk_pcbc_alg = { | ||
566 | .cra_name = "pcbc(aes)", | ||
567 | .cra_driver_name = "pcbc-aes-aesni", | ||
568 | .cra_priority = 400, | ||
569 | .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC, | ||
570 | .cra_blocksize = AES_BLOCK_SIZE, | ||
571 | .cra_ctxsize = sizeof(struct async_aes_ctx), | ||
572 | .cra_alignmask = 0, | ||
573 | .cra_type = &crypto_ablkcipher_type, | ||
574 | .cra_module = THIS_MODULE, | ||
575 | .cra_list = LIST_HEAD_INIT(ablk_pcbc_alg.cra_list), | ||
576 | .cra_init = ablk_pcbc_init, | ||
577 | .cra_exit = ablk_exit, | ||
578 | .cra_u = { | ||
579 | .ablkcipher = { | ||
580 | .min_keysize = AES_MIN_KEY_SIZE, | ||
581 | .max_keysize = AES_MAX_KEY_SIZE, | ||
582 | .ivsize = AES_BLOCK_SIZE, | ||
583 | .setkey = ablk_set_key, | ||
584 | .encrypt = ablk_encrypt, | ||
585 | .decrypt = ablk_decrypt, | ||
586 | }, | ||
587 | }, | ||
588 | }; | ||
589 | #endif | ||
590 | |||
591 | #ifdef HAS_XTS | ||
592 | static int ablk_xts_init(struct crypto_tfm *tfm) | ||
593 | { | ||
594 | struct cryptd_ablkcipher *cryptd_tfm; | ||
595 | |||
596 | cryptd_tfm = cryptd_alloc_ablkcipher("fpu(xts(__driver-aes-aesni))", | ||
597 | 0, 0); | ||
598 | if (IS_ERR(cryptd_tfm)) | ||
599 | return PTR_ERR(cryptd_tfm); | ||
600 | ablk_init_common(tfm, cryptd_tfm); | ||
601 | return 0; | ||
602 | } | ||
603 | |||
604 | static struct crypto_alg ablk_xts_alg = { | ||
605 | .cra_name = "xts(aes)", | ||
606 | .cra_driver_name = "xts-aes-aesni", | ||
607 | .cra_priority = 400, | ||
608 | .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC, | ||
609 | .cra_blocksize = AES_BLOCK_SIZE, | ||
610 | .cra_ctxsize = sizeof(struct async_aes_ctx), | ||
611 | .cra_alignmask = 0, | ||
612 | .cra_type = &crypto_ablkcipher_type, | ||
613 | .cra_module = THIS_MODULE, | ||
614 | .cra_list = LIST_HEAD_INIT(ablk_xts_alg.cra_list), | ||
615 | .cra_init = ablk_xts_init, | ||
616 | .cra_exit = ablk_exit, | ||
617 | .cra_u = { | ||
618 | .ablkcipher = { | ||
619 | .min_keysize = 2 * AES_MIN_KEY_SIZE, | ||
620 | .max_keysize = 2 * AES_MAX_KEY_SIZE, | ||
621 | .ivsize = AES_BLOCK_SIZE, | ||
622 | .setkey = ablk_set_key, | ||
623 | .encrypt = ablk_encrypt, | ||
624 | .decrypt = ablk_decrypt, | ||
625 | }, | ||
626 | }, | ||
627 | }; | ||
628 | #endif | ||
629 | |||
414 | static int __init aesni_init(void) | 630 | static int __init aesni_init(void) |
415 | { | 631 | { |
416 | int err; | 632 | int err; |
@@ -421,6 +637,8 @@ static int __init aesni_init(void) | |||
421 | } | 637 | } |
422 | if ((err = crypto_register_alg(&aesni_alg))) | 638 | if ((err = crypto_register_alg(&aesni_alg))) |
423 | goto aes_err; | 639 | goto aes_err; |
640 | if ((err = crypto_register_alg(&__aesni_alg))) | ||
641 | goto __aes_err; | ||
424 | if ((err = crypto_register_alg(&blk_ecb_alg))) | 642 | if ((err = crypto_register_alg(&blk_ecb_alg))) |
425 | goto blk_ecb_err; | 643 | goto blk_ecb_err; |
426 | if ((err = crypto_register_alg(&blk_cbc_alg))) | 644 | if ((err = crypto_register_alg(&blk_cbc_alg))) |
@@ -429,9 +647,41 @@ static int __init aesni_init(void) | |||
429 | goto ablk_ecb_err; | 647 | goto ablk_ecb_err; |
430 | if ((err = crypto_register_alg(&ablk_cbc_alg))) | 648 | if ((err = crypto_register_alg(&ablk_cbc_alg))) |
431 | goto ablk_cbc_err; | 649 | goto ablk_cbc_err; |
650 | #ifdef HAS_CTR | ||
651 | if ((err = crypto_register_alg(&ablk_ctr_alg))) | ||
652 | goto ablk_ctr_err; | ||
653 | #endif | ||
654 | #ifdef HAS_LRW | ||
655 | if ((err = crypto_register_alg(&ablk_lrw_alg))) | ||
656 | goto ablk_lrw_err; | ||
657 | #endif | ||
658 | #ifdef HAS_PCBC | ||
659 | if ((err = crypto_register_alg(&ablk_pcbc_alg))) | ||
660 | goto ablk_pcbc_err; | ||
661 | #endif | ||
662 | #ifdef HAS_XTS | ||
663 | if ((err = crypto_register_alg(&ablk_xts_alg))) | ||
664 | goto ablk_xts_err; | ||
665 | #endif | ||
432 | 666 | ||
433 | return err; | 667 | return err; |
434 | 668 | ||
669 | #ifdef HAS_XTS | ||
670 | ablk_xts_err: | ||
671 | #endif | ||
672 | #ifdef HAS_PCBC | ||
673 | crypto_unregister_alg(&ablk_pcbc_alg); | ||
674 | ablk_pcbc_err: | ||
675 | #endif | ||
676 | #ifdef HAS_LRW | ||
677 | crypto_unregister_alg(&ablk_lrw_alg); | ||
678 | ablk_lrw_err: | ||
679 | #endif | ||
680 | #ifdef HAS_CTR | ||
681 | crypto_unregister_alg(&ablk_ctr_alg); | ||
682 | ablk_ctr_err: | ||
683 | #endif | ||
684 | crypto_unregister_alg(&ablk_cbc_alg); | ||
435 | ablk_cbc_err: | 685 | ablk_cbc_err: |
436 | crypto_unregister_alg(&ablk_ecb_alg); | 686 | crypto_unregister_alg(&ablk_ecb_alg); |
437 | ablk_ecb_err: | 687 | ablk_ecb_err: |
@@ -439,6 +689,8 @@ ablk_ecb_err: | |||
439 | blk_cbc_err: | 689 | blk_cbc_err: |
440 | crypto_unregister_alg(&blk_ecb_alg); | 690 | crypto_unregister_alg(&blk_ecb_alg); |
441 | blk_ecb_err: | 691 | blk_ecb_err: |
692 | crypto_unregister_alg(&__aesni_alg); | ||
693 | __aes_err: | ||
442 | crypto_unregister_alg(&aesni_alg); | 694 | crypto_unregister_alg(&aesni_alg); |
443 | aes_err: | 695 | aes_err: |
444 | return err; | 696 | return err; |
@@ -446,10 +698,23 @@ aes_err: | |||
446 | 698 | ||
447 | static void __exit aesni_exit(void) | 699 | static void __exit aesni_exit(void) |
448 | { | 700 | { |
701 | #ifdef HAS_XTS | ||
702 | crypto_unregister_alg(&ablk_xts_alg); | ||
703 | #endif | ||
704 | #ifdef HAS_PCBC | ||
705 | crypto_unregister_alg(&ablk_pcbc_alg); | ||
706 | #endif | ||
707 | #ifdef HAS_LRW | ||
708 | crypto_unregister_alg(&ablk_lrw_alg); | ||
709 | #endif | ||
710 | #ifdef HAS_CTR | ||
711 | crypto_unregister_alg(&ablk_ctr_alg); | ||
712 | #endif | ||
449 | crypto_unregister_alg(&ablk_cbc_alg); | 713 | crypto_unregister_alg(&ablk_cbc_alg); |
450 | crypto_unregister_alg(&ablk_ecb_alg); | 714 | crypto_unregister_alg(&ablk_ecb_alg); |
451 | crypto_unregister_alg(&blk_cbc_alg); | 715 | crypto_unregister_alg(&blk_cbc_alg); |
452 | crypto_unregister_alg(&blk_ecb_alg); | 716 | crypto_unregister_alg(&blk_ecb_alg); |
717 | crypto_unregister_alg(&__aesni_alg); | ||
453 | crypto_unregister_alg(&aesni_alg); | 718 | crypto_unregister_alg(&aesni_alg); |
454 | } | 719 | } |
455 | 720 | ||
diff --git a/arch/x86/crypto/fpu.c b/arch/x86/crypto/fpu.c new file mode 100644 index 000000000000..5f9781a3815f --- /dev/null +++ b/arch/x86/crypto/fpu.c | |||
@@ -0,0 +1,166 @@ | |||
1 | /* | ||
2 | * FPU: Wrapper for blkcipher touching fpu | ||
3 | * | ||
4 | * Copyright (c) Intel Corp. | ||
5 | * Author: Huang Ying <ying.huang@intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the Free | ||
9 | * Software Foundation; either version 2 of the License, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <crypto/algapi.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <asm/i387.h> | ||
20 | |||
21 | struct crypto_fpu_ctx { | ||
22 | struct crypto_blkcipher *child; | ||
23 | }; | ||
24 | |||
25 | static int crypto_fpu_setkey(struct crypto_tfm *parent, const u8 *key, | ||
26 | unsigned int keylen) | ||
27 | { | ||
28 | struct crypto_fpu_ctx *ctx = crypto_tfm_ctx(parent); | ||
29 | struct crypto_blkcipher *child = ctx->child; | ||
30 | int err; | ||
31 | |||
32 | crypto_blkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); | ||
33 | crypto_blkcipher_set_flags(child, crypto_tfm_get_flags(parent) & | ||
34 | CRYPTO_TFM_REQ_MASK); | ||
35 | err = crypto_blkcipher_setkey(child, key, keylen); | ||
36 | crypto_tfm_set_flags(parent, crypto_blkcipher_get_flags(child) & | ||
37 | CRYPTO_TFM_RES_MASK); | ||
38 | return err; | ||
39 | } | ||
40 | |||
41 | static int crypto_fpu_encrypt(struct blkcipher_desc *desc_in, | ||
42 | struct scatterlist *dst, struct scatterlist *src, | ||
43 | unsigned int nbytes) | ||
44 | { | ||
45 | int err; | ||
46 | struct crypto_fpu_ctx *ctx = crypto_blkcipher_ctx(desc_in->tfm); | ||
47 | struct crypto_blkcipher *child = ctx->child; | ||
48 | struct blkcipher_desc desc = { | ||
49 | .tfm = child, | ||
50 | .info = desc_in->info, | ||
51 | .flags = desc_in->flags, | ||
52 | }; | ||
53 | |||
54 | kernel_fpu_begin(); | ||
55 | err = crypto_blkcipher_crt(desc.tfm)->encrypt(&desc, dst, src, nbytes); | ||
56 | kernel_fpu_end(); | ||
57 | return err; | ||
58 | } | ||
59 | |||
60 | static int crypto_fpu_decrypt(struct blkcipher_desc *desc_in, | ||
61 | struct scatterlist *dst, struct scatterlist *src, | ||
62 | unsigned int nbytes) | ||
63 | { | ||
64 | int err; | ||
65 | struct crypto_fpu_ctx *ctx = crypto_blkcipher_ctx(desc_in->tfm); | ||
66 | struct crypto_blkcipher *child = ctx->child; | ||
67 | struct blkcipher_desc desc = { | ||
68 | .tfm = child, | ||
69 | .info = desc_in->info, | ||
70 | .flags = desc_in->flags, | ||
71 | }; | ||
72 | |||
73 | kernel_fpu_begin(); | ||
74 | err = crypto_blkcipher_crt(desc.tfm)->decrypt(&desc, dst, src, nbytes); | ||
75 | kernel_fpu_end(); | ||
76 | return err; | ||
77 | } | ||
78 | |||
79 | static int crypto_fpu_init_tfm(struct crypto_tfm *tfm) | ||
80 | { | ||
81 | struct crypto_instance *inst = crypto_tfm_alg_instance(tfm); | ||
82 | struct crypto_spawn *spawn = crypto_instance_ctx(inst); | ||
83 | struct crypto_fpu_ctx *ctx = crypto_tfm_ctx(tfm); | ||
84 | struct crypto_blkcipher *cipher; | ||
85 | |||
86 | cipher = crypto_spawn_blkcipher(spawn); | ||
87 | if (IS_ERR(cipher)) | ||
88 | return PTR_ERR(cipher); | ||
89 | |||
90 | ctx->child = cipher; | ||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | static void crypto_fpu_exit_tfm(struct crypto_tfm *tfm) | ||
95 | { | ||
96 | struct crypto_fpu_ctx *ctx = crypto_tfm_ctx(tfm); | ||
97 | crypto_free_blkcipher(ctx->child); | ||
98 | } | ||
99 | |||
100 | static struct crypto_instance *crypto_fpu_alloc(struct rtattr **tb) | ||
101 | { | ||
102 | struct crypto_instance *inst; | ||
103 | struct crypto_alg *alg; | ||
104 | int err; | ||
105 | |||
106 | err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER); | ||
107 | if (err) | ||
108 | return ERR_PTR(err); | ||
109 | |||
110 | alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_BLKCIPHER, | ||
111 | CRYPTO_ALG_TYPE_MASK); | ||
112 | if (IS_ERR(alg)) | ||
113 | return ERR_CAST(alg); | ||
114 | |||
115 | inst = crypto_alloc_instance("fpu", alg); | ||
116 | if (IS_ERR(inst)) | ||
117 | goto out_put_alg; | ||
118 | |||
119 | inst->alg.cra_flags = alg->cra_flags; | ||
120 | inst->alg.cra_priority = alg->cra_priority; | ||
121 | inst->alg.cra_blocksize = alg->cra_blocksize; | ||
122 | inst->alg.cra_alignmask = alg->cra_alignmask; | ||
123 | inst->alg.cra_type = alg->cra_type; | ||
124 | inst->alg.cra_blkcipher.ivsize = alg->cra_blkcipher.ivsize; | ||
125 | inst->alg.cra_blkcipher.min_keysize = alg->cra_blkcipher.min_keysize; | ||
126 | inst->alg.cra_blkcipher.max_keysize = alg->cra_blkcipher.max_keysize; | ||
127 | inst->alg.cra_ctxsize = sizeof(struct crypto_fpu_ctx); | ||
128 | inst->alg.cra_init = crypto_fpu_init_tfm; | ||
129 | inst->alg.cra_exit = crypto_fpu_exit_tfm; | ||
130 | inst->alg.cra_blkcipher.setkey = crypto_fpu_setkey; | ||
131 | inst->alg.cra_blkcipher.encrypt = crypto_fpu_encrypt; | ||
132 | inst->alg.cra_blkcipher.decrypt = crypto_fpu_decrypt; | ||
133 | |||
134 | out_put_alg: | ||
135 | crypto_mod_put(alg); | ||
136 | return inst; | ||
137 | } | ||
138 | |||
139 | static void crypto_fpu_free(struct crypto_instance *inst) | ||
140 | { | ||
141 | crypto_drop_spawn(crypto_instance_ctx(inst)); | ||
142 | kfree(inst); | ||
143 | } | ||
144 | |||
145 | static struct crypto_template crypto_fpu_tmpl = { | ||
146 | .name = "fpu", | ||
147 | .alloc = crypto_fpu_alloc, | ||
148 | .free = crypto_fpu_free, | ||
149 | .module = THIS_MODULE, | ||
150 | }; | ||
151 | |||
152 | static int __init crypto_fpu_module_init(void) | ||
153 | { | ||
154 | return crypto_register_template(&crypto_fpu_tmpl); | ||
155 | } | ||
156 | |||
157 | static void __exit crypto_fpu_module_exit(void) | ||
158 | { | ||
159 | crypto_unregister_template(&crypto_fpu_tmpl); | ||
160 | } | ||
161 | |||
162 | module_init(crypto_fpu_module_init); | ||
163 | module_exit(crypto_fpu_module_exit); | ||
164 | |||
165 | MODULE_LICENSE("GPL"); | ||
166 | MODULE_DESCRIPTION("FPU block cipher wrapper"); | ||
diff --git a/arch/x86/include/asm/entry_arch.h b/arch/x86/include/asm/entry_arch.h index d750a10ccad6..ff8cbfa07851 100644 --- a/arch/x86/include/asm/entry_arch.h +++ b/arch/x86/include/asm/entry_arch.h | |||
@@ -14,6 +14,7 @@ BUILD_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR) | |||
14 | BUILD_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR) | 14 | BUILD_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR) |
15 | BUILD_INTERRUPT(call_function_single_interrupt,CALL_FUNCTION_SINGLE_VECTOR) | 15 | BUILD_INTERRUPT(call_function_single_interrupt,CALL_FUNCTION_SINGLE_VECTOR) |
16 | BUILD_INTERRUPT(irq_move_cleanup_interrupt,IRQ_MOVE_CLEANUP_VECTOR) | 16 | BUILD_INTERRUPT(irq_move_cleanup_interrupt,IRQ_MOVE_CLEANUP_VECTOR) |
17 | BUILD_INTERRUPT(reboot_interrupt,REBOOT_VECTOR) | ||
17 | 18 | ||
18 | BUILD_INTERRUPT3(invalidate_interrupt0,INVALIDATE_TLB_VECTOR_START+0, | 19 | BUILD_INTERRUPT3(invalidate_interrupt0,INVALIDATE_TLB_VECTOR_START+0, |
19 | smp_invalidate_interrupt) | 20 | smp_invalidate_interrupt) |
@@ -52,8 +53,16 @@ BUILD_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR) | |||
52 | BUILD_INTERRUPT(perf_pending_interrupt, LOCAL_PENDING_VECTOR) | 53 | BUILD_INTERRUPT(perf_pending_interrupt, LOCAL_PENDING_VECTOR) |
53 | #endif | 54 | #endif |
54 | 55 | ||
55 | #ifdef CONFIG_X86_MCE_P4THERMAL | 56 | #ifdef CONFIG_X86_THERMAL_VECTOR |
56 | BUILD_INTERRUPT(thermal_interrupt,THERMAL_APIC_VECTOR) | 57 | BUILD_INTERRUPT(thermal_interrupt,THERMAL_APIC_VECTOR) |
57 | #endif | 58 | #endif |
58 | 59 | ||
60 | #ifdef CONFIG_X86_MCE_THRESHOLD | ||
61 | BUILD_INTERRUPT(threshold_interrupt,THRESHOLD_APIC_VECTOR) | ||
62 | #endif | ||
63 | |||
64 | #ifdef CONFIG_X86_NEW_MCE | ||
65 | BUILD_INTERRUPT(mce_self_interrupt,MCE_SELF_VECTOR) | ||
66 | #endif | ||
67 | |||
59 | #endif | 68 | #endif |
diff --git a/arch/x86/include/asm/hardirq.h b/arch/x86/include/asm/hardirq.h index 9ebc5c255032..82e3e8f01043 100644 --- a/arch/x86/include/asm/hardirq.h +++ b/arch/x86/include/asm/hardirq.h | |||
@@ -22,7 +22,7 @@ typedef struct { | |||
22 | #endif | 22 | #endif |
23 | #ifdef CONFIG_X86_MCE | 23 | #ifdef CONFIG_X86_MCE |
24 | unsigned int irq_thermal_count; | 24 | unsigned int irq_thermal_count; |
25 | # ifdef CONFIG_X86_64 | 25 | # ifdef CONFIG_X86_MCE_THRESHOLD |
26 | unsigned int irq_threshold_count; | 26 | unsigned int irq_threshold_count; |
27 | # endif | 27 | # endif |
28 | #endif | 28 | #endif |
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h index 6df45f639666..ba180d93b08c 100644 --- a/arch/x86/include/asm/hw_irq.h +++ b/arch/x86/include/asm/hw_irq.h | |||
@@ -34,6 +34,7 @@ extern void perf_pending_interrupt(void); | |||
34 | extern void spurious_interrupt(void); | 34 | extern void spurious_interrupt(void); |
35 | extern void thermal_interrupt(void); | 35 | extern void thermal_interrupt(void); |
36 | extern void reschedule_interrupt(void); | 36 | extern void reschedule_interrupt(void); |
37 | extern void mce_self_interrupt(void); | ||
37 | 38 | ||
38 | extern void invalidate_interrupt(void); | 39 | extern void invalidate_interrupt(void); |
39 | extern void invalidate_interrupt0(void); | 40 | extern void invalidate_interrupt0(void); |
@@ -46,6 +47,7 @@ extern void invalidate_interrupt6(void); | |||
46 | extern void invalidate_interrupt7(void); | 47 | extern void invalidate_interrupt7(void); |
47 | 48 | ||
48 | extern void irq_move_cleanup_interrupt(void); | 49 | extern void irq_move_cleanup_interrupt(void); |
50 | extern void reboot_interrupt(void); | ||
49 | extern void threshold_interrupt(void); | 51 | extern void threshold_interrupt(void); |
50 | 52 | ||
51 | extern void call_function_interrupt(void); | 53 | extern void call_function_interrupt(void); |
diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h index e997be98c9b9..5b21f0ec3df2 100644 --- a/arch/x86/include/asm/irq_vectors.h +++ b/arch/x86/include/asm/irq_vectors.h | |||
@@ -25,6 +25,7 @@ | |||
25 | */ | 25 | */ |
26 | 26 | ||
27 | #define NMI_VECTOR 0x02 | 27 | #define NMI_VECTOR 0x02 |
28 | #define MCE_VECTOR 0x12 | ||
28 | 29 | ||
29 | /* | 30 | /* |
30 | * IDT vectors usable for external interrupt sources start | 31 | * IDT vectors usable for external interrupt sources start |
@@ -87,13 +88,8 @@ | |||
87 | #define CALL_FUNCTION_VECTOR 0xfc | 88 | #define CALL_FUNCTION_VECTOR 0xfc |
88 | #define CALL_FUNCTION_SINGLE_VECTOR 0xfb | 89 | #define CALL_FUNCTION_SINGLE_VECTOR 0xfb |
89 | #define THERMAL_APIC_VECTOR 0xfa | 90 | #define THERMAL_APIC_VECTOR 0xfa |
90 | 91 | #define THRESHOLD_APIC_VECTOR 0xf9 | |
91 | #ifdef CONFIG_X86_32 | 92 | #define REBOOT_VECTOR 0xf8 |
92 | /* 0xf8 - 0xf9 : free */ | ||
93 | #else | ||
94 | # define THRESHOLD_APIC_VECTOR 0xf9 | ||
95 | # define UV_BAU_MESSAGE 0xf8 | ||
96 | #endif | ||
97 | 93 | ||
98 | /* f0-f7 used for spreading out TLB flushes: */ | 94 | /* f0-f7 used for spreading out TLB flushes: */ |
99 | #define INVALIDATE_TLB_VECTOR_END 0xf7 | 95 | #define INVALIDATE_TLB_VECTOR_END 0xf7 |
@@ -117,6 +113,13 @@ | |||
117 | */ | 113 | */ |
118 | #define LOCAL_PENDING_VECTOR 0xec | 114 | #define LOCAL_PENDING_VECTOR 0xec |
119 | 115 | ||
116 | #define UV_BAU_MESSAGE 0xec | ||
117 | |||
118 | /* | ||
119 | * Self IPI vector for machine checks | ||
120 | */ | ||
121 | #define MCE_SELF_VECTOR 0xeb | ||
122 | |||
120 | /* | 123 | /* |
121 | * First APIC vector available to drivers: (vectors 0x30-0xee) we | 124 | * First APIC vector available to drivers: (vectors 0x30-0xee) we |
122 | * start at 0x31(0x41) to spread out vectors evenly between priority | 125 | * start at 0x31(0x41) to spread out vectors evenly between priority |
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h index 4f8c199584e7..540a466e50f5 100644 --- a/arch/x86/include/asm/mce.h +++ b/arch/x86/include/asm/mce.h | |||
@@ -1,8 +1,6 @@ | |||
1 | #ifndef _ASM_X86_MCE_H | 1 | #ifndef _ASM_X86_MCE_H |
2 | #define _ASM_X86_MCE_H | 2 | #define _ASM_X86_MCE_H |
3 | 3 | ||
4 | #ifdef __x86_64__ | ||
5 | |||
6 | #include <linux/types.h> | 4 | #include <linux/types.h> |
7 | #include <asm/ioctls.h> | 5 | #include <asm/ioctls.h> |
8 | 6 | ||
@@ -10,21 +8,35 @@ | |||
10 | * Machine Check support for x86 | 8 | * Machine Check support for x86 |
11 | */ | 9 | */ |
12 | 10 | ||
13 | #define MCG_CTL_P (1UL<<8) /* MCG_CAP register available */ | 11 | #define MCG_BANKCNT_MASK 0xff /* Number of Banks */ |
14 | #define MCG_EXT_P (1ULL<<9) /* Extended registers available */ | 12 | #define MCG_CTL_P (1ULL<<8) /* MCG_CAP register available */ |
15 | #define MCG_CMCI_P (1ULL<<10) /* CMCI supported */ | 13 | #define MCG_EXT_P (1ULL<<9) /* Extended registers available */ |
16 | 14 | #define MCG_CMCI_P (1ULL<<10) /* CMCI supported */ | |
17 | #define MCG_STATUS_RIPV (1UL<<0) /* restart ip valid */ | 15 | #define MCG_EXT_CNT_MASK 0xff0000 /* Number of Extended registers */ |
18 | #define MCG_STATUS_EIPV (1UL<<1) /* ip points to correct instruction */ | 16 | #define MCG_EXT_CNT_SHIFT 16 |
19 | #define MCG_STATUS_MCIP (1UL<<2) /* machine check in progress */ | 17 | #define MCG_EXT_CNT(c) (((c) & MCG_EXT_CNT_MASK) >> MCG_EXT_CNT_SHIFT) |
20 | 18 | #define MCG_SER_P (1ULL<<24) /* MCA recovery/new status bits */ | |
21 | #define MCI_STATUS_VAL (1UL<<63) /* valid error */ | 19 | |
22 | #define MCI_STATUS_OVER (1UL<<62) /* previous errors lost */ | 20 | #define MCG_STATUS_RIPV (1ULL<<0) /* restart ip valid */ |
23 | #define MCI_STATUS_UC (1UL<<61) /* uncorrected error */ | 21 | #define MCG_STATUS_EIPV (1ULL<<1) /* ip points to correct instruction */ |
24 | #define MCI_STATUS_EN (1UL<<60) /* error enabled */ | 22 | #define MCG_STATUS_MCIP (1ULL<<2) /* machine check in progress */ |
25 | #define MCI_STATUS_MISCV (1UL<<59) /* misc error reg. valid */ | 23 | |
26 | #define MCI_STATUS_ADDRV (1UL<<58) /* addr reg. valid */ | 24 | #define MCI_STATUS_VAL (1ULL<<63) /* valid error */ |
27 | #define MCI_STATUS_PCC (1UL<<57) /* processor context corrupt */ | 25 | #define MCI_STATUS_OVER (1ULL<<62) /* previous errors lost */ |
26 | #define MCI_STATUS_UC (1ULL<<61) /* uncorrected error */ | ||
27 | #define MCI_STATUS_EN (1ULL<<60) /* error enabled */ | ||
28 | #define MCI_STATUS_MISCV (1ULL<<59) /* misc error reg. valid */ | ||
29 | #define MCI_STATUS_ADDRV (1ULL<<58) /* addr reg. valid */ | ||
30 | #define MCI_STATUS_PCC (1ULL<<57) /* processor context corrupt */ | ||
31 | #define MCI_STATUS_S (1ULL<<56) /* Signaled machine check */ | ||
32 | #define MCI_STATUS_AR (1ULL<<55) /* Action required */ | ||
33 | |||
34 | /* MISC register defines */ | ||
35 | #define MCM_ADDR_SEGOFF 0 /* segment offset */ | ||
36 | #define MCM_ADDR_LINEAR 1 /* linear address */ | ||
37 | #define MCM_ADDR_PHYS 2 /* physical address */ | ||
38 | #define MCM_ADDR_MEM 3 /* memory address */ | ||
39 | #define MCM_ADDR_GENERIC 7 /* generic */ | ||
28 | 40 | ||
29 | /* Fields are zero when not available */ | 41 | /* Fields are zero when not available */ |
30 | struct mce { | 42 | struct mce { |
@@ -34,13 +46,19 @@ struct mce { | |||
34 | __u64 mcgstatus; | 46 | __u64 mcgstatus; |
35 | __u64 ip; | 47 | __u64 ip; |
36 | __u64 tsc; /* cpu time stamp counter */ | 48 | __u64 tsc; /* cpu time stamp counter */ |
37 | __u64 res1; /* for future extension */ | 49 | __u64 time; /* wall time_t when error was detected */ |
38 | __u64 res2; /* dito. */ | 50 | __u8 cpuvendor; /* cpu vendor as encoded in system.h */ |
51 | __u8 pad1; | ||
52 | __u16 pad2; | ||
53 | __u32 cpuid; /* CPUID 1 EAX */ | ||
39 | __u8 cs; /* code segment */ | 54 | __u8 cs; /* code segment */ |
40 | __u8 bank; /* machine check bank */ | 55 | __u8 bank; /* machine check bank */ |
41 | __u8 cpu; /* cpu that raised the error */ | 56 | __u8 cpu; /* cpu number; obsolete; use extcpu now */ |
42 | __u8 finished; /* entry is valid */ | 57 | __u8 finished; /* entry is valid */ |
43 | __u32 pad; | 58 | __u32 extcpu; /* linux cpu number that detected the error */ |
59 | __u32 socketid; /* CPU socket ID */ | ||
60 | __u32 apicid; /* CPU initial apic ID */ | ||
61 | __u64 mcgcap; /* MCGCAP MSR: machine check capabilities of CPU */ | ||
44 | }; | 62 | }; |
45 | 63 | ||
46 | /* | 64 | /* |
@@ -57,7 +75,7 @@ struct mce_log { | |||
57 | unsigned len; /* = MCE_LOG_LEN */ | 75 | unsigned len; /* = MCE_LOG_LEN */ |
58 | unsigned next; | 76 | unsigned next; |
59 | unsigned flags; | 77 | unsigned flags; |
60 | unsigned pad0; | 78 | unsigned recordlen; /* length of struct mce */ |
61 | struct mce entry[MCE_LOG_LEN]; | 79 | struct mce entry[MCE_LOG_LEN]; |
62 | }; | 80 | }; |
63 | 81 | ||
@@ -82,19 +100,16 @@ struct mce_log { | |||
82 | #define K8_MCE_THRESHOLD_BANK_5 (MCE_THRESHOLD_BASE + 5 * 9) | 100 | #define K8_MCE_THRESHOLD_BANK_5 (MCE_THRESHOLD_BASE + 5 * 9) |
83 | #define K8_MCE_THRESHOLD_DRAM_ECC (MCE_THRESHOLD_BANK_4 + 0) | 101 | #define K8_MCE_THRESHOLD_DRAM_ECC (MCE_THRESHOLD_BANK_4 + 0) |
84 | 102 | ||
85 | #endif /* __x86_64__ */ | ||
86 | |||
87 | #ifdef __KERNEL__ | 103 | #ifdef __KERNEL__ |
88 | 104 | ||
89 | #ifdef CONFIG_X86_32 | ||
90 | extern int mce_disabled; | 105 | extern int mce_disabled; |
91 | #else /* CONFIG_X86_32 */ | ||
92 | 106 | ||
93 | #include <asm/atomic.h> | 107 | #include <asm/atomic.h> |
108 | #include <linux/percpu.h> | ||
94 | 109 | ||
95 | void mce_setup(struct mce *m); | 110 | void mce_setup(struct mce *m); |
96 | void mce_log(struct mce *m); | 111 | void mce_log(struct mce *m); |
97 | DECLARE_PER_CPU(struct sys_device, device_mce); | 112 | DECLARE_PER_CPU(struct sys_device, mce_dev); |
98 | extern void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu); | 113 | extern void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu); |
99 | 114 | ||
100 | /* | 115 | /* |
@@ -104,6 +119,8 @@ extern void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu); | |||
104 | #define MAX_NR_BANKS (MCE_EXTENDED_BANK - 1) | 119 | #define MAX_NR_BANKS (MCE_EXTENDED_BANK - 1) |
105 | 120 | ||
106 | #ifdef CONFIG_X86_MCE_INTEL | 121 | #ifdef CONFIG_X86_MCE_INTEL |
122 | extern int mce_cmci_disabled; | ||
123 | extern int mce_ignore_ce; | ||
107 | void mce_intel_feature_init(struct cpuinfo_x86 *c); | 124 | void mce_intel_feature_init(struct cpuinfo_x86 *c); |
108 | void cmci_clear(void); | 125 | void cmci_clear(void); |
109 | void cmci_reenable(void); | 126 | void cmci_reenable(void); |
@@ -123,13 +140,16 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c); | |||
123 | static inline void mce_amd_feature_init(struct cpuinfo_x86 *c) { } | 140 | static inline void mce_amd_feature_init(struct cpuinfo_x86 *c) { } |
124 | #endif | 141 | #endif |
125 | 142 | ||
126 | extern int mce_available(struct cpuinfo_x86 *c); | 143 | int mce_available(struct cpuinfo_x86 *c); |
144 | |||
145 | DECLARE_PER_CPU(unsigned, mce_exception_count); | ||
146 | DECLARE_PER_CPU(unsigned, mce_poll_count); | ||
127 | 147 | ||
128 | void mce_log_therm_throt_event(__u64 status); | 148 | void mce_log_therm_throt_event(__u64 status); |
129 | 149 | ||
130 | extern atomic_t mce_entry; | 150 | extern atomic_t mce_entry; |
131 | 151 | ||
132 | extern void do_machine_check(struct pt_regs *, long); | 152 | void do_machine_check(struct pt_regs *, long); |
133 | 153 | ||
134 | typedef DECLARE_BITMAP(mce_banks_t, MAX_NR_BANKS); | 154 | typedef DECLARE_BITMAP(mce_banks_t, MAX_NR_BANKS); |
135 | DECLARE_PER_CPU(mce_banks_t, mce_poll_banks); | 155 | DECLARE_PER_CPU(mce_banks_t, mce_poll_banks); |
@@ -139,14 +159,16 @@ enum mcp_flags { | |||
139 | MCP_UC = (1 << 1), /* log uncorrected errors */ | 159 | MCP_UC = (1 << 1), /* log uncorrected errors */ |
140 | MCP_DONTLOG = (1 << 2), /* only clear, don't log */ | 160 | MCP_DONTLOG = (1 << 2), /* only clear, don't log */ |
141 | }; | 161 | }; |
142 | extern void machine_check_poll(enum mcp_flags flags, mce_banks_t *b); | 162 | void machine_check_poll(enum mcp_flags flags, mce_banks_t *b); |
143 | 163 | ||
144 | extern int mce_notify_user(void); | 164 | int mce_notify_irq(void); |
165 | void mce_notify_process(void); | ||
145 | 166 | ||
146 | #endif /* !CONFIG_X86_32 */ | 167 | DECLARE_PER_CPU(struct mce, injectm); |
168 | extern struct file_operations mce_chrdev_ops; | ||
147 | 169 | ||
148 | #ifdef CONFIG_X86_MCE | 170 | #ifdef CONFIG_X86_MCE |
149 | extern void mcheck_init(struct cpuinfo_x86 *c); | 171 | void mcheck_init(struct cpuinfo_x86 *c); |
150 | #else | 172 | #else |
151 | #define mcheck_init(c) do { } while (0) | 173 | #define mcheck_init(c) do { } while (0) |
152 | #endif | 174 | #endif |
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 4d58d04fca83..1692fb5050e3 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h | |||
@@ -207,7 +207,14 @@ | |||
207 | 207 | ||
208 | #define MSR_IA32_THERM_CONTROL 0x0000019a | 208 | #define MSR_IA32_THERM_CONTROL 0x0000019a |
209 | #define MSR_IA32_THERM_INTERRUPT 0x0000019b | 209 | #define MSR_IA32_THERM_INTERRUPT 0x0000019b |
210 | |||
211 | #define THERM_INT_LOW_ENABLE (1 << 0) | ||
212 | #define THERM_INT_HIGH_ENABLE (1 << 1) | ||
213 | |||
210 | #define MSR_IA32_THERM_STATUS 0x0000019c | 214 | #define MSR_IA32_THERM_STATUS 0x0000019c |
215 | |||
216 | #define THERM_STATUS_PROCHOT (1 << 0) | ||
217 | |||
211 | #define MSR_IA32_MISC_ENABLE 0x000001a0 | 218 | #define MSR_IA32_MISC_ENABLE 0x000001a0 |
212 | 219 | ||
213 | /* MISC_ENABLE bits: architectural */ | 220 | /* MISC_ENABLE bits: architectural */ |
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 076d3881f3da..8c7c042ecad1 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
@@ -899,7 +899,7 @@ void clear_local_APIC(void) | |||
899 | } | 899 | } |
900 | 900 | ||
901 | /* lets not touch this if we didn't frob it */ | 901 | /* lets not touch this if we didn't frob it */ |
902 | #if defined(CONFIG_X86_MCE_P4THERMAL) || defined(CONFIG_X86_MCE_INTEL) | 902 | #ifdef CONFIG_X86_THERMAL_VECTOR |
903 | if (maxlvt >= 5) { | 903 | if (maxlvt >= 5) { |
904 | v = apic_read(APIC_LVTTHMR); | 904 | v = apic_read(APIC_LVTTHMR); |
905 | apic_write(APIC_LVTTHMR, v | APIC_LVT_MASKED); | 905 | apic_write(APIC_LVTTHMR, v | APIC_LVT_MASKED); |
@@ -2017,7 +2017,7 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state) | |||
2017 | apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR); | 2017 | apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR); |
2018 | apic_pm_state.apic_tmict = apic_read(APIC_TMICT); | 2018 | apic_pm_state.apic_tmict = apic_read(APIC_TMICT); |
2019 | apic_pm_state.apic_tdcr = apic_read(APIC_TDCR); | 2019 | apic_pm_state.apic_tdcr = apic_read(APIC_TDCR); |
2020 | #if defined(CONFIG_X86_MCE_P4THERMAL) || defined(CONFIG_X86_MCE_INTEL) | 2020 | #ifdef CONFIG_X86_THERMAL_VECTOR |
2021 | if (maxlvt >= 5) | 2021 | if (maxlvt >= 5) |
2022 | apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR); | 2022 | apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR); |
2023 | #endif | 2023 | #endif |
diff --git a/arch/x86/kernel/apic/nmi.c b/arch/x86/kernel/apic/nmi.c index a691302dc3ff..b3025b43b63a 100644 --- a/arch/x86/kernel/apic/nmi.c +++ b/arch/x86/kernel/apic/nmi.c | |||
@@ -66,7 +66,7 @@ static inline unsigned int get_nmi_count(int cpu) | |||
66 | 66 | ||
67 | static inline int mce_in_progress(void) | 67 | static inline int mce_in_progress(void) |
68 | { | 68 | { |
69 | #if defined(CONFIG_X86_64) && defined(CONFIG_X86_MCE) | 69 | #if defined(CONFIG_X86_NEW_MCE) |
70 | return atomic_read(&mce_entry) > 0; | 70 | return atomic_read(&mce_entry) > 0; |
71 | #endif | 71 | #endif |
72 | return 0; | 72 | return 0; |
diff --git a/arch/x86/kernel/cpu/mcheck/Makefile b/arch/x86/kernel/cpu/mcheck/Makefile index b2f89829bbe8..45004faf67ea 100644 --- a/arch/x86/kernel/cpu/mcheck/Makefile +++ b/arch/x86/kernel/cpu/mcheck/Makefile | |||
@@ -1,7 +1,11 @@ | |||
1 | obj-y = mce_$(BITS).o therm_throt.o | 1 | obj-y = mce.o therm_throt.o |
2 | 2 | ||
3 | obj-$(CONFIG_X86_32) += k7.o p4.o p5.o p6.o winchip.o | 3 | obj-$(CONFIG_X86_NEW_MCE) += mce-severity.o |
4 | obj-$(CONFIG_X86_MCE_INTEL) += mce_intel_64.o | 4 | obj-$(CONFIG_X86_OLD_MCE) += k7.o p4.o p6.o |
5 | obj-$(CONFIG_X86_ANCIENT_MCE) += winchip.o p5.o | ||
6 | obj-$(CONFIG_X86_MCE_P4THERMAL) += mce_intel.o | ||
7 | obj-$(CONFIG_X86_MCE_INTEL) += mce_intel_64.o mce_intel.o | ||
5 | obj-$(CONFIG_X86_MCE_AMD) += mce_amd_64.o | 8 | obj-$(CONFIG_X86_MCE_AMD) += mce_amd_64.o |
6 | obj-$(CONFIG_X86_MCE_NONFATAL) += non-fatal.o | 9 | obj-$(CONFIG_X86_MCE_NONFATAL) += non-fatal.o |
7 | obj-$(CONFIG_X86_MCE_THRESHOLD) += threshold.o | 10 | obj-$(CONFIG_X86_MCE_THRESHOLD) += threshold.o |
11 | obj-$(CONFIG_X86_MCE_INJECT) += mce-inject.o | ||
diff --git a/arch/x86/kernel/cpu/mcheck/k7.c b/arch/x86/kernel/cpu/mcheck/k7.c index dd3af6e7b39a..89e510424152 100644 --- a/arch/x86/kernel/cpu/mcheck/k7.c +++ b/arch/x86/kernel/cpu/mcheck/k7.c | |||
@@ -2,11 +2,10 @@ | |||
2 | * Athlon specific Machine Check Exception Reporting | 2 | * Athlon specific Machine Check Exception Reporting |
3 | * (C) Copyright 2002 Dave Jones <davej@redhat.com> | 3 | * (C) Copyright 2002 Dave Jones <davej@redhat.com> |
4 | */ | 4 | */ |
5 | |||
6 | #include <linux/init.h> | ||
7 | #include <linux/types.h> | ||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/interrupt.h> | 5 | #include <linux/interrupt.h> |
6 | #include <linux/kernel.h> | ||
7 | #include <linux/types.h> | ||
8 | #include <linux/init.h> | ||
10 | #include <linux/smp.h> | 9 | #include <linux/smp.h> |
11 | 10 | ||
12 | #include <asm/processor.h> | 11 | #include <asm/processor.h> |
@@ -15,12 +14,12 @@ | |||
15 | 14 | ||
16 | #include "mce.h" | 15 | #include "mce.h" |
17 | 16 | ||
18 | /* Machine Check Handler For AMD Athlon/Duron */ | 17 | /* Machine Check Handler For AMD Athlon/Duron: */ |
19 | static void k7_machine_check(struct pt_regs *regs, long error_code) | 18 | static void k7_machine_check(struct pt_regs *regs, long error_code) |
20 | { | 19 | { |
21 | int recover = 1; | ||
22 | u32 alow, ahigh, high, low; | 20 | u32 alow, ahigh, high, low; |
23 | u32 mcgstl, mcgsth; | 21 | u32 mcgstl, mcgsth; |
22 | int recover = 1; | ||
24 | int i; | 23 | int i; |
25 | 24 | ||
26 | rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth); | 25 | rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth); |
@@ -32,15 +31,19 @@ static void k7_machine_check(struct pt_regs *regs, long error_code) | |||
32 | 31 | ||
33 | for (i = 1; i < nr_mce_banks; i++) { | 32 | for (i = 1; i < nr_mce_banks; i++) { |
34 | rdmsr(MSR_IA32_MC0_STATUS+i*4, low, high); | 33 | rdmsr(MSR_IA32_MC0_STATUS+i*4, low, high); |
35 | if (high&(1<<31)) { | 34 | if (high & (1<<31)) { |
36 | char misc[20]; | 35 | char misc[20]; |
37 | char addr[24]; | 36 | char addr[24]; |
38 | misc[0] = addr[0] = '\0'; | 37 | |
38 | misc[0] = '\0'; | ||
39 | addr[0] = '\0'; | ||
40 | |||
39 | if (high & (1<<29)) | 41 | if (high & (1<<29)) |
40 | recover |= 1; | 42 | recover |= 1; |
41 | if (high & (1<<25)) | 43 | if (high & (1<<25)) |
42 | recover |= 2; | 44 | recover |= 2; |
43 | high &= ~(1<<31); | 45 | high &= ~(1<<31); |
46 | |||
44 | if (high & (1<<27)) { | 47 | if (high & (1<<27)) { |
45 | rdmsr(MSR_IA32_MC0_MISC+i*4, alow, ahigh); | 48 | rdmsr(MSR_IA32_MC0_MISC+i*4, alow, ahigh); |
46 | snprintf(misc, 20, "[%08x%08x]", ahigh, alow); | 49 | snprintf(misc, 20, "[%08x%08x]", ahigh, alow); |
@@ -49,27 +52,31 @@ static void k7_machine_check(struct pt_regs *regs, long error_code) | |||
49 | rdmsr(MSR_IA32_MC0_ADDR+i*4, alow, ahigh); | 52 | rdmsr(MSR_IA32_MC0_ADDR+i*4, alow, ahigh); |
50 | snprintf(addr, 24, " at %08x%08x", ahigh, alow); | 53 | snprintf(addr, 24, " at %08x%08x", ahigh, alow); |
51 | } | 54 | } |
55 | |||
52 | printk(KERN_EMERG "CPU %d: Bank %d: %08x%08x%s%s\n", | 56 | printk(KERN_EMERG "CPU %d: Bank %d: %08x%08x%s%s\n", |
53 | smp_processor_id(), i, high, low, misc, addr); | 57 | smp_processor_id(), i, high, low, misc, addr); |
54 | /* Clear it */ | 58 | |
59 | /* Clear it: */ | ||
55 | wrmsr(MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL); | 60 | wrmsr(MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL); |
56 | /* Serialize */ | 61 | /* Serialize: */ |
57 | wmb(); | 62 | wmb(); |
58 | add_taint(TAINT_MACHINE_CHECK); | 63 | add_taint(TAINT_MACHINE_CHECK); |
59 | } | 64 | } |
60 | } | 65 | } |
61 | 66 | ||
62 | if (recover&2) | 67 | if (recover & 2) |
63 | panic("CPU context corrupt"); | 68 | panic("CPU context corrupt"); |
64 | if (recover&1) | 69 | if (recover & 1) |
65 | panic("Unable to continue"); | 70 | panic("Unable to continue"); |
71 | |||
66 | printk(KERN_EMERG "Attempting to continue.\n"); | 72 | printk(KERN_EMERG "Attempting to continue.\n"); |
73 | |||
67 | mcgstl &= ~(1<<2); | 74 | mcgstl &= ~(1<<2); |
68 | wrmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth); | 75 | wrmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth); |
69 | } | 76 | } |
70 | 77 | ||
71 | 78 | ||
72 | /* AMD K7 machine check is Intel like */ | 79 | /* AMD K7 machine check is Intel like: */ |
73 | void amd_mcheck_init(struct cpuinfo_x86 *c) | 80 | void amd_mcheck_init(struct cpuinfo_x86 *c) |
74 | { | 81 | { |
75 | u32 l, h; | 82 | u32 l, h; |
@@ -79,21 +86,26 @@ void amd_mcheck_init(struct cpuinfo_x86 *c) | |||
79 | return; | 86 | return; |
80 | 87 | ||
81 | machine_check_vector = k7_machine_check; | 88 | machine_check_vector = k7_machine_check; |
89 | /* Make sure the vector pointer is visible before we enable MCEs: */ | ||
82 | wmb(); | 90 | wmb(); |
83 | 91 | ||
84 | printk(KERN_INFO "Intel machine check architecture supported.\n"); | 92 | printk(KERN_INFO "Intel machine check architecture supported.\n"); |
93 | |||
85 | rdmsr(MSR_IA32_MCG_CAP, l, h); | 94 | rdmsr(MSR_IA32_MCG_CAP, l, h); |
86 | if (l & (1<<8)) /* Control register present ? */ | 95 | if (l & (1<<8)) /* Control register present ? */ |
87 | wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff); | 96 | wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff); |
88 | nr_mce_banks = l & 0xff; | 97 | nr_mce_banks = l & 0xff; |
89 | 98 | ||
90 | /* Clear status for MC index 0 separately, we don't touch CTL, | 99 | /* |
91 | * as some K7 Athlons cause spurious MCEs when its enabled. */ | 100 | * Clear status for MC index 0 separately, we don't touch CTL, |
101 | * as some K7 Athlons cause spurious MCEs when its enabled: | ||
102 | */ | ||
92 | if (boot_cpu_data.x86 == 6) { | 103 | if (boot_cpu_data.x86 == 6) { |
93 | wrmsr(MSR_IA32_MC0_STATUS, 0x0, 0x0); | 104 | wrmsr(MSR_IA32_MC0_STATUS, 0x0, 0x0); |
94 | i = 1; | 105 | i = 1; |
95 | } else | 106 | } else |
96 | i = 0; | 107 | i = 0; |
108 | |||
97 | for (; i < nr_mce_banks; i++) { | 109 | for (; i < nr_mce_banks; i++) { |
98 | wrmsr(MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff); | 110 | wrmsr(MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff); |
99 | wrmsr(MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0); | 111 | wrmsr(MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0); |
diff --git a/arch/x86/kernel/cpu/mcheck/mce-inject.c b/arch/x86/kernel/cpu/mcheck/mce-inject.c new file mode 100644 index 000000000000..a3a235a53f09 --- /dev/null +++ b/arch/x86/kernel/cpu/mcheck/mce-inject.c | |||
@@ -0,0 +1,127 @@ | |||
1 | /* | ||
2 | * Machine check injection support. | ||
3 | * Copyright 2008 Intel Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License | ||
7 | * as published by the Free Software Foundation; version 2 | ||
8 | * of the License. | ||
9 | * | ||
10 | * Authors: | ||
11 | * Andi Kleen | ||
12 | * Ying Huang | ||
13 | */ | ||
14 | #include <linux/uaccess.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/timer.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/string.h> | ||
19 | #include <linux/fs.h> | ||
20 | #include <linux/smp.h> | ||
21 | #include <asm/mce.h> | ||
22 | |||
23 | /* Update fake mce registers on current CPU. */ | ||
24 | static void inject_mce(struct mce *m) | ||
25 | { | ||
26 | struct mce *i = &per_cpu(injectm, m->extcpu); | ||
27 | |||
28 | /* Make sure noone reads partially written injectm */ | ||
29 | i->finished = 0; | ||
30 | mb(); | ||
31 | m->finished = 0; | ||
32 | /* First set the fields after finished */ | ||
33 | i->extcpu = m->extcpu; | ||
34 | mb(); | ||
35 | /* Now write record in order, finished last (except above) */ | ||
36 | memcpy(i, m, sizeof(struct mce)); | ||
37 | /* Finally activate it */ | ||
38 | mb(); | ||
39 | i->finished = 1; | ||
40 | } | ||
41 | |||
42 | struct delayed_mce { | ||
43 | struct timer_list timer; | ||
44 | struct mce m; | ||
45 | }; | ||
46 | |||
47 | /* Inject mce on current CPU */ | ||
48 | static void raise_mce(unsigned long data) | ||
49 | { | ||
50 | struct delayed_mce *dm = (struct delayed_mce *)data; | ||
51 | struct mce *m = &dm->m; | ||
52 | int cpu = m->extcpu; | ||
53 | |||
54 | inject_mce(m); | ||
55 | if (m->status & MCI_STATUS_UC) { | ||
56 | struct pt_regs regs; | ||
57 | memset(®s, 0, sizeof(struct pt_regs)); | ||
58 | regs.ip = m->ip; | ||
59 | regs.cs = m->cs; | ||
60 | printk(KERN_INFO "Triggering MCE exception on CPU %d\n", cpu); | ||
61 | do_machine_check(®s, 0); | ||
62 | printk(KERN_INFO "MCE exception done on CPU %d\n", cpu); | ||
63 | } else { | ||
64 | mce_banks_t b; | ||
65 | memset(&b, 0xff, sizeof(mce_banks_t)); | ||
66 | printk(KERN_INFO "Starting machine check poll CPU %d\n", cpu); | ||
67 | machine_check_poll(0, &b); | ||
68 | mce_notify_irq(); | ||
69 | printk(KERN_INFO "Finished machine check poll on CPU %d\n", | ||
70 | cpu); | ||
71 | } | ||
72 | kfree(dm); | ||
73 | } | ||
74 | |||
75 | /* Error injection interface */ | ||
76 | static ssize_t mce_write(struct file *filp, const char __user *ubuf, | ||
77 | size_t usize, loff_t *off) | ||
78 | { | ||
79 | struct delayed_mce *dm; | ||
80 | struct mce m; | ||
81 | |||
82 | if (!capable(CAP_SYS_ADMIN)) | ||
83 | return -EPERM; | ||
84 | /* | ||
85 | * There are some cases where real MSR reads could slip | ||
86 | * through. | ||
87 | */ | ||
88 | if (!boot_cpu_has(X86_FEATURE_MCE) || !boot_cpu_has(X86_FEATURE_MCA)) | ||
89 | return -EIO; | ||
90 | |||
91 | if ((unsigned long)usize > sizeof(struct mce)) | ||
92 | usize = sizeof(struct mce); | ||
93 | if (copy_from_user(&m, ubuf, usize)) | ||
94 | return -EFAULT; | ||
95 | |||
96 | if (m.extcpu >= num_possible_cpus() || !cpu_online(m.extcpu)) | ||
97 | return -EINVAL; | ||
98 | |||
99 | dm = kmalloc(sizeof(struct delayed_mce), GFP_KERNEL); | ||
100 | if (!dm) | ||
101 | return -ENOMEM; | ||
102 | |||
103 | /* | ||
104 | * Need to give user space some time to set everything up, | ||
105 | * so do it a jiffie or two later everywhere. | ||
106 | * Should we use a hrtimer here for better synchronization? | ||
107 | */ | ||
108 | memcpy(&dm->m, &m, sizeof(struct mce)); | ||
109 | setup_timer(&dm->timer, raise_mce, (unsigned long)dm); | ||
110 | dm->timer.expires = jiffies + 2; | ||
111 | add_timer_on(&dm->timer, m.extcpu); | ||
112 | return usize; | ||
113 | } | ||
114 | |||
115 | static int inject_init(void) | ||
116 | { | ||
117 | printk(KERN_INFO "Machine check injector initialized\n"); | ||
118 | mce_chrdev_ops.write = mce_write; | ||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | module_init(inject_init); | ||
123 | /* | ||
124 | * Cannot tolerate unloading currently because we cannot | ||
125 | * guarantee all openers of mce_chrdev will get a reference to us. | ||
126 | */ | ||
127 | MODULE_LICENSE("GPL"); | ||
diff --git a/arch/x86/kernel/cpu/mcheck/mce-internal.h b/arch/x86/kernel/cpu/mcheck/mce-internal.h new file mode 100644 index 000000000000..54dcb8ff12e5 --- /dev/null +++ b/arch/x86/kernel/cpu/mcheck/mce-internal.h | |||
@@ -0,0 +1,15 @@ | |||
1 | #include <asm/mce.h> | ||
2 | |||
3 | enum severity_level { | ||
4 | MCE_NO_SEVERITY, | ||
5 | MCE_KEEP_SEVERITY, | ||
6 | MCE_SOME_SEVERITY, | ||
7 | MCE_AO_SEVERITY, | ||
8 | MCE_UC_SEVERITY, | ||
9 | MCE_AR_SEVERITY, | ||
10 | MCE_PANIC_SEVERITY, | ||
11 | }; | ||
12 | |||
13 | int mce_severity(struct mce *a, int tolerant, char **msg); | ||
14 | |||
15 | extern int mce_ser; | ||
diff --git a/arch/x86/kernel/cpu/mcheck/mce-severity.c b/arch/x86/kernel/cpu/mcheck/mce-severity.c new file mode 100644 index 000000000000..ff0807f97056 --- /dev/null +++ b/arch/x86/kernel/cpu/mcheck/mce-severity.c | |||
@@ -0,0 +1,218 @@ | |||
1 | /* | ||
2 | * MCE grading rules. | ||
3 | * Copyright 2008, 2009 Intel Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License | ||
7 | * as published by the Free Software Foundation; version 2 | ||
8 | * of the License. | ||
9 | * | ||
10 | * Author: Andi Kleen | ||
11 | */ | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/seq_file.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/debugfs.h> | ||
16 | #include <asm/mce.h> | ||
17 | |||
18 | #include "mce-internal.h" | ||
19 | |||
20 | /* | ||
21 | * Grade an mce by severity. In general the most severe ones are processed | ||
22 | * first. Since there are quite a lot of combinations test the bits in a | ||
23 | * table-driven way. The rules are simply processed in order, first | ||
24 | * match wins. | ||
25 | * | ||
26 | * Note this is only used for machine check exceptions, the corrected | ||
27 | * errors use much simpler rules. The exceptions still check for the corrected | ||
28 | * errors, but only to leave them alone for the CMCI handler (except for | ||
29 | * panic situations) | ||
30 | */ | ||
31 | |||
32 | enum context { IN_KERNEL = 1, IN_USER = 2 }; | ||
33 | enum ser { SER_REQUIRED = 1, NO_SER = 2 }; | ||
34 | |||
35 | static struct severity { | ||
36 | u64 mask; | ||
37 | u64 result; | ||
38 | unsigned char sev; | ||
39 | unsigned char mcgmask; | ||
40 | unsigned char mcgres; | ||
41 | unsigned char ser; | ||
42 | unsigned char context; | ||
43 | unsigned char covered; | ||
44 | char *msg; | ||
45 | } severities[] = { | ||
46 | #define KERNEL .context = IN_KERNEL | ||
47 | #define USER .context = IN_USER | ||
48 | #define SER .ser = SER_REQUIRED | ||
49 | #define NOSER .ser = NO_SER | ||
50 | #define SEV(s) .sev = MCE_ ## s ## _SEVERITY | ||
51 | #define BITCLR(x, s, m, r...) { .mask = x, .result = 0, SEV(s), .msg = m, ## r } | ||
52 | #define BITSET(x, s, m, r...) { .mask = x, .result = x, SEV(s), .msg = m, ## r } | ||
53 | #define MCGMASK(x, res, s, m, r...) \ | ||
54 | { .mcgmask = x, .mcgres = res, SEV(s), .msg = m, ## r } | ||
55 | #define MASK(x, y, s, m, r...) \ | ||
56 | { .mask = x, .result = y, SEV(s), .msg = m, ## r } | ||
57 | #define MCI_UC_S (MCI_STATUS_UC|MCI_STATUS_S) | ||
58 | #define MCI_UC_SAR (MCI_STATUS_UC|MCI_STATUS_S|MCI_STATUS_AR) | ||
59 | #define MCACOD 0xffff | ||
60 | |||
61 | BITCLR(MCI_STATUS_VAL, NO, "Invalid"), | ||
62 | BITCLR(MCI_STATUS_EN, NO, "Not enabled"), | ||
63 | BITSET(MCI_STATUS_PCC, PANIC, "Processor context corrupt"), | ||
64 | /* When MCIP is not set something is very confused */ | ||
65 | MCGMASK(MCG_STATUS_MCIP, 0, PANIC, "MCIP not set in MCA handler"), | ||
66 | /* Neither return not error IP -- no chance to recover -> PANIC */ | ||
67 | MCGMASK(MCG_STATUS_RIPV|MCG_STATUS_EIPV, 0, PANIC, | ||
68 | "Neither restart nor error IP"), | ||
69 | MCGMASK(MCG_STATUS_RIPV, 0, PANIC, "In kernel and no restart IP", | ||
70 | KERNEL), | ||
71 | BITCLR(MCI_STATUS_UC, KEEP, "Corrected error", NOSER), | ||
72 | MASK(MCI_STATUS_OVER|MCI_STATUS_UC|MCI_STATUS_EN, MCI_STATUS_UC, SOME, | ||
73 | "Spurious not enabled", SER), | ||
74 | |||
75 | /* ignore OVER for UCNA */ | ||
76 | MASK(MCI_UC_SAR, MCI_STATUS_UC, KEEP, | ||
77 | "Uncorrected no action required", SER), | ||
78 | MASK(MCI_STATUS_OVER|MCI_UC_SAR, MCI_STATUS_UC|MCI_STATUS_AR, PANIC, | ||
79 | "Illegal combination (UCNA with AR=1)", SER), | ||
80 | MASK(MCI_STATUS_S, 0, KEEP, "Non signalled machine check", SER), | ||
81 | |||
82 | /* AR add known MCACODs here */ | ||
83 | MASK(MCI_STATUS_OVER|MCI_UC_SAR, MCI_STATUS_OVER|MCI_UC_SAR, PANIC, | ||
84 | "Action required with lost events", SER), | ||
85 | MASK(MCI_STATUS_OVER|MCI_UC_SAR|MCACOD, MCI_UC_SAR, PANIC, | ||
86 | "Action required; unknown MCACOD", SER), | ||
87 | |||
88 | /* known AO MCACODs: */ | ||
89 | MASK(MCI_UC_SAR|MCI_STATUS_OVER|0xfff0, MCI_UC_S|0xc0, AO, | ||
90 | "Action optional: memory scrubbing error", SER), | ||
91 | MASK(MCI_UC_SAR|MCI_STATUS_OVER|MCACOD, MCI_UC_S|0x17a, AO, | ||
92 | "Action optional: last level cache writeback error", SER), | ||
93 | |||
94 | MASK(MCI_STATUS_OVER|MCI_UC_SAR, MCI_UC_S, SOME, | ||
95 | "Action optional unknown MCACOD", SER), | ||
96 | MASK(MCI_STATUS_OVER|MCI_UC_SAR, MCI_UC_S|MCI_STATUS_OVER, SOME, | ||
97 | "Action optional with lost events", SER), | ||
98 | BITSET(MCI_STATUS_UC|MCI_STATUS_OVER, PANIC, "Overflowed uncorrected"), | ||
99 | BITSET(MCI_STATUS_UC, UC, "Uncorrected"), | ||
100 | BITSET(0, SOME, "No match") /* always matches. keep at end */ | ||
101 | }; | ||
102 | |||
103 | /* | ||
104 | * If the EIPV bit is set, it means the saved IP is the | ||
105 | * instruction which caused the MCE. | ||
106 | */ | ||
107 | static int error_context(struct mce *m) | ||
108 | { | ||
109 | if (m->mcgstatus & MCG_STATUS_EIPV) | ||
110 | return (m->ip && (m->cs & 3) == 3) ? IN_USER : IN_KERNEL; | ||
111 | /* Unknown, assume kernel */ | ||
112 | return IN_KERNEL; | ||
113 | } | ||
114 | |||
115 | int mce_severity(struct mce *a, int tolerant, char **msg) | ||
116 | { | ||
117 | enum context ctx = error_context(a); | ||
118 | struct severity *s; | ||
119 | |||
120 | for (s = severities;; s++) { | ||
121 | if ((a->status & s->mask) != s->result) | ||
122 | continue; | ||
123 | if ((a->mcgstatus & s->mcgmask) != s->mcgres) | ||
124 | continue; | ||
125 | if (s->ser == SER_REQUIRED && !mce_ser) | ||
126 | continue; | ||
127 | if (s->ser == NO_SER && mce_ser) | ||
128 | continue; | ||
129 | if (s->context && ctx != s->context) | ||
130 | continue; | ||
131 | if (msg) | ||
132 | *msg = s->msg; | ||
133 | s->covered = 1; | ||
134 | if (s->sev >= MCE_UC_SEVERITY && ctx == IN_KERNEL) { | ||
135 | if (panic_on_oops || tolerant < 1) | ||
136 | return MCE_PANIC_SEVERITY; | ||
137 | } | ||
138 | return s->sev; | ||
139 | } | ||
140 | } | ||
141 | |||
142 | static void *s_start(struct seq_file *f, loff_t *pos) | ||
143 | { | ||
144 | if (*pos >= ARRAY_SIZE(severities)) | ||
145 | return NULL; | ||
146 | return &severities[*pos]; | ||
147 | } | ||
148 | |||
149 | static void *s_next(struct seq_file *f, void *data, loff_t *pos) | ||
150 | { | ||
151 | if (++(*pos) >= ARRAY_SIZE(severities)) | ||
152 | return NULL; | ||
153 | return &severities[*pos]; | ||
154 | } | ||
155 | |||
156 | static void s_stop(struct seq_file *f, void *data) | ||
157 | { | ||
158 | } | ||
159 | |||
160 | static int s_show(struct seq_file *f, void *data) | ||
161 | { | ||
162 | struct severity *ser = data; | ||
163 | seq_printf(f, "%d\t%s\n", ser->covered, ser->msg); | ||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | static const struct seq_operations severities_seq_ops = { | ||
168 | .start = s_start, | ||
169 | .next = s_next, | ||
170 | .stop = s_stop, | ||
171 | .show = s_show, | ||
172 | }; | ||
173 | |||
174 | static int severities_coverage_open(struct inode *inode, struct file *file) | ||
175 | { | ||
176 | return seq_open(file, &severities_seq_ops); | ||
177 | } | ||
178 | |||
179 | static ssize_t severities_coverage_write(struct file *file, | ||
180 | const char __user *ubuf, | ||
181 | size_t count, loff_t *ppos) | ||
182 | { | ||
183 | int i; | ||
184 | for (i = 0; i < ARRAY_SIZE(severities); i++) | ||
185 | severities[i].covered = 0; | ||
186 | return count; | ||
187 | } | ||
188 | |||
189 | static const struct file_operations severities_coverage_fops = { | ||
190 | .open = severities_coverage_open, | ||
191 | .release = seq_release, | ||
192 | .read = seq_read, | ||
193 | .write = severities_coverage_write, | ||
194 | }; | ||
195 | |||
196 | static int __init severities_debugfs_init(void) | ||
197 | { | ||
198 | struct dentry *dmce = NULL, *fseverities_coverage = NULL; | ||
199 | |||
200 | dmce = debugfs_create_dir("mce", NULL); | ||
201 | if (dmce == NULL) | ||
202 | goto err_out; | ||
203 | fseverities_coverage = debugfs_create_file("severities-coverage", | ||
204 | 0444, dmce, NULL, | ||
205 | &severities_coverage_fops); | ||
206 | if (fseverities_coverage == NULL) | ||
207 | goto err_out; | ||
208 | |||
209 | return 0; | ||
210 | |||
211 | err_out: | ||
212 | if (fseverities_coverage) | ||
213 | debugfs_remove(fseverities_coverage); | ||
214 | if (dmce) | ||
215 | debugfs_remove(dmce); | ||
216 | return -ENOMEM; | ||
217 | } | ||
218 | late_initcall(severities_debugfs_init); | ||
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c new file mode 100644 index 000000000000..fabba15e4558 --- /dev/null +++ b/arch/x86/kernel/cpu/mcheck/mce.c | |||
@@ -0,0 +1,1964 @@ | |||
1 | /* | ||
2 | * Machine check handler. | ||
3 | * | ||
4 | * K8 parts Copyright 2002,2003 Andi Kleen, SuSE Labs. | ||
5 | * Rest from unknown author(s). | ||
6 | * 2004 Andi Kleen. Rewrote most of it. | ||
7 | * Copyright 2008 Intel Corporation | ||
8 | * Author: Andi Kleen | ||
9 | */ | ||
10 | #include <linux/thread_info.h> | ||
11 | #include <linux/capability.h> | ||
12 | #include <linux/miscdevice.h> | ||
13 | #include <linux/interrupt.h> | ||
14 | #include <linux/ratelimit.h> | ||
15 | #include <linux/kallsyms.h> | ||
16 | #include <linux/rcupdate.h> | ||
17 | #include <linux/kobject.h> | ||
18 | #include <linux/uaccess.h> | ||
19 | #include <linux/kdebug.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/percpu.h> | ||
22 | #include <linux/string.h> | ||
23 | #include <linux/sysdev.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <linux/ctype.h> | ||
26 | #include <linux/sched.h> | ||
27 | #include <linux/sysfs.h> | ||
28 | #include <linux/types.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/kmod.h> | ||
31 | #include <linux/poll.h> | ||
32 | #include <linux/nmi.h> | ||
33 | #include <linux/cpu.h> | ||
34 | #include <linux/smp.h> | ||
35 | #include <linux/fs.h> | ||
36 | #include <linux/mm.h> | ||
37 | |||
38 | #include <asm/processor.h> | ||
39 | #include <asm/hw_irq.h> | ||
40 | #include <asm/apic.h> | ||
41 | #include <asm/idle.h> | ||
42 | #include <asm/ipi.h> | ||
43 | #include <asm/mce.h> | ||
44 | #include <asm/msr.h> | ||
45 | |||
46 | #include "mce-internal.h" | ||
47 | #include "mce.h" | ||
48 | |||
49 | /* Handle unconfigured int18 (should never happen) */ | ||
50 | static void unexpected_machine_check(struct pt_regs *regs, long error_code) | ||
51 | { | ||
52 | printk(KERN_ERR "CPU#%d: Unexpected int18 (Machine Check).\n", | ||
53 | smp_processor_id()); | ||
54 | } | ||
55 | |||
56 | /* Call the installed machine check handler for this CPU setup. */ | ||
57 | void (*machine_check_vector)(struct pt_regs *, long error_code) = | ||
58 | unexpected_machine_check; | ||
59 | |||
60 | int mce_disabled; | ||
61 | |||
62 | #ifdef CONFIG_X86_NEW_MCE | ||
63 | |||
64 | #define MISC_MCELOG_MINOR 227 | ||
65 | |||
66 | #define SPINUNIT 100 /* 100ns */ | ||
67 | |||
68 | atomic_t mce_entry; | ||
69 | |||
70 | DEFINE_PER_CPU(unsigned, mce_exception_count); | ||
71 | |||
72 | /* | ||
73 | * Tolerant levels: | ||
74 | * 0: always panic on uncorrected errors, log corrected errors | ||
75 | * 1: panic or SIGBUS on uncorrected errors, log corrected errors | ||
76 | * 2: SIGBUS or log uncorrected errors (if possible), log corrected errors | ||
77 | * 3: never panic or SIGBUS, log all errors (for testing only) | ||
78 | */ | ||
79 | static int tolerant = 1; | ||
80 | static int banks; | ||
81 | static u64 *bank; | ||
82 | static unsigned long notify_user; | ||
83 | static int rip_msr; | ||
84 | static int mce_bootlog = -1; | ||
85 | static int monarch_timeout = -1; | ||
86 | static int mce_panic_timeout; | ||
87 | static int mce_dont_log_ce; | ||
88 | int mce_cmci_disabled; | ||
89 | int mce_ignore_ce; | ||
90 | int mce_ser; | ||
91 | |||
92 | static char trigger[128]; | ||
93 | static char *trigger_argv[2] = { trigger, NULL }; | ||
94 | |||
95 | static unsigned long dont_init_banks; | ||
96 | |||
97 | static DECLARE_WAIT_QUEUE_HEAD(mce_wait); | ||
98 | static DEFINE_PER_CPU(struct mce, mces_seen); | ||
99 | static int cpu_missing; | ||
100 | |||
101 | |||
102 | /* MCA banks polled by the period polling timer for corrected events */ | ||
103 | DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = { | ||
104 | [0 ... BITS_TO_LONGS(MAX_NR_BANKS)-1] = ~0UL | ||
105 | }; | ||
106 | |||
107 | static inline int skip_bank_init(int i) | ||
108 | { | ||
109 | return i < BITS_PER_LONG && test_bit(i, &dont_init_banks); | ||
110 | } | ||
111 | |||
112 | static DEFINE_PER_CPU(struct work_struct, mce_work); | ||
113 | |||
114 | /* Do initial initialization of a struct mce */ | ||
115 | void mce_setup(struct mce *m) | ||
116 | { | ||
117 | memset(m, 0, sizeof(struct mce)); | ||
118 | m->cpu = m->extcpu = smp_processor_id(); | ||
119 | rdtscll(m->tsc); | ||
120 | /* We hope get_seconds stays lockless */ | ||
121 | m->time = get_seconds(); | ||
122 | m->cpuvendor = boot_cpu_data.x86_vendor; | ||
123 | m->cpuid = cpuid_eax(1); | ||
124 | #ifdef CONFIG_SMP | ||
125 | m->socketid = cpu_data(m->extcpu).phys_proc_id; | ||
126 | #endif | ||
127 | m->apicid = cpu_data(m->extcpu).initial_apicid; | ||
128 | rdmsrl(MSR_IA32_MCG_CAP, m->mcgcap); | ||
129 | } | ||
130 | |||
131 | DEFINE_PER_CPU(struct mce, injectm); | ||
132 | EXPORT_PER_CPU_SYMBOL_GPL(injectm); | ||
133 | |||
134 | /* | ||
135 | * Lockless MCE logging infrastructure. | ||
136 | * This avoids deadlocks on printk locks without having to break locks. Also | ||
137 | * separate MCEs from kernel messages to avoid bogus bug reports. | ||
138 | */ | ||
139 | |||
140 | static struct mce_log mcelog = { | ||
141 | .signature = MCE_LOG_SIGNATURE, | ||
142 | .len = MCE_LOG_LEN, | ||
143 | .recordlen = sizeof(struct mce), | ||
144 | }; | ||
145 | |||
146 | void mce_log(struct mce *mce) | ||
147 | { | ||
148 | unsigned next, entry; | ||
149 | |||
150 | mce->finished = 0; | ||
151 | wmb(); | ||
152 | for (;;) { | ||
153 | entry = rcu_dereference(mcelog.next); | ||
154 | for (;;) { | ||
155 | /* | ||
156 | * When the buffer fills up discard new entries. | ||
157 | * Assume that the earlier errors are the more | ||
158 | * interesting ones: | ||
159 | */ | ||
160 | if (entry >= MCE_LOG_LEN) { | ||
161 | set_bit(MCE_OVERFLOW, | ||
162 | (unsigned long *)&mcelog.flags); | ||
163 | return; | ||
164 | } | ||
165 | /* Old left over entry. Skip: */ | ||
166 | if (mcelog.entry[entry].finished) { | ||
167 | entry++; | ||
168 | continue; | ||
169 | } | ||
170 | break; | ||
171 | } | ||
172 | smp_rmb(); | ||
173 | next = entry + 1; | ||
174 | if (cmpxchg(&mcelog.next, entry, next) == entry) | ||
175 | break; | ||
176 | } | ||
177 | memcpy(mcelog.entry + entry, mce, sizeof(struct mce)); | ||
178 | wmb(); | ||
179 | mcelog.entry[entry].finished = 1; | ||
180 | wmb(); | ||
181 | |||
182 | mce->finished = 1; | ||
183 | set_bit(0, ¬ify_user); | ||
184 | } | ||
185 | |||
186 | static void print_mce(struct mce *m) | ||
187 | { | ||
188 | printk(KERN_EMERG | ||
189 | "CPU %d: Machine Check Exception: %16Lx Bank %d: %016Lx\n", | ||
190 | m->extcpu, m->mcgstatus, m->bank, m->status); | ||
191 | if (m->ip) { | ||
192 | printk(KERN_EMERG "RIP%s %02x:<%016Lx> ", | ||
193 | !(m->mcgstatus & MCG_STATUS_EIPV) ? " !INEXACT!" : "", | ||
194 | m->cs, m->ip); | ||
195 | if (m->cs == __KERNEL_CS) | ||
196 | print_symbol("{%s}", m->ip); | ||
197 | printk("\n"); | ||
198 | } | ||
199 | printk(KERN_EMERG "TSC %llx ", m->tsc); | ||
200 | if (m->addr) | ||
201 | printk("ADDR %llx ", m->addr); | ||
202 | if (m->misc) | ||
203 | printk("MISC %llx ", m->misc); | ||
204 | printk("\n"); | ||
205 | printk(KERN_EMERG "PROCESSOR %u:%x TIME %llu SOCKET %u APIC %x\n", | ||
206 | m->cpuvendor, m->cpuid, m->time, m->socketid, | ||
207 | m->apicid); | ||
208 | } | ||
209 | |||
210 | static void print_mce_head(void) | ||
211 | { | ||
212 | printk(KERN_EMERG "\n" KERN_EMERG "HARDWARE ERROR\n"); | ||
213 | } | ||
214 | |||
215 | static void print_mce_tail(void) | ||
216 | { | ||
217 | printk(KERN_EMERG "This is not a software problem!\n" | ||
218 | KERN_EMERG "Run through mcelog --ascii to decode and contact your hardware vendor\n"); | ||
219 | } | ||
220 | |||
221 | #define PANIC_TIMEOUT 5 /* 5 seconds */ | ||
222 | |||
223 | static atomic_t mce_paniced; | ||
224 | |||
225 | /* Panic in progress. Enable interrupts and wait for final IPI */ | ||
226 | static void wait_for_panic(void) | ||
227 | { | ||
228 | long timeout = PANIC_TIMEOUT*USEC_PER_SEC; | ||
229 | preempt_disable(); | ||
230 | local_irq_enable(); | ||
231 | while (timeout-- > 0) | ||
232 | udelay(1); | ||
233 | if (panic_timeout == 0) | ||
234 | panic_timeout = mce_panic_timeout; | ||
235 | panic("Panicing machine check CPU died"); | ||
236 | } | ||
237 | |||
238 | static void mce_panic(char *msg, struct mce *final, char *exp) | ||
239 | { | ||
240 | int i; | ||
241 | |||
242 | /* | ||
243 | * Make sure only one CPU runs in machine check panic | ||
244 | */ | ||
245 | if (atomic_add_return(1, &mce_paniced) > 1) | ||
246 | wait_for_panic(); | ||
247 | barrier(); | ||
248 | |||
249 | bust_spinlocks(1); | ||
250 | console_verbose(); | ||
251 | print_mce_head(); | ||
252 | /* First print corrected ones that are still unlogged */ | ||
253 | for (i = 0; i < MCE_LOG_LEN; i++) { | ||
254 | struct mce *m = &mcelog.entry[i]; | ||
255 | if (!(m->status & MCI_STATUS_VAL)) | ||
256 | continue; | ||
257 | if (!(m->status & MCI_STATUS_UC)) | ||
258 | print_mce(m); | ||
259 | } | ||
260 | /* Now print uncorrected but with the final one last */ | ||
261 | for (i = 0; i < MCE_LOG_LEN; i++) { | ||
262 | struct mce *m = &mcelog.entry[i]; | ||
263 | if (!(m->status & MCI_STATUS_VAL)) | ||
264 | continue; | ||
265 | if (!(m->status & MCI_STATUS_UC)) | ||
266 | continue; | ||
267 | if (!final || memcmp(m, final, sizeof(struct mce))) | ||
268 | print_mce(m); | ||
269 | } | ||
270 | if (final) | ||
271 | print_mce(final); | ||
272 | if (cpu_missing) | ||
273 | printk(KERN_EMERG "Some CPUs didn't answer in synchronization\n"); | ||
274 | print_mce_tail(); | ||
275 | if (exp) | ||
276 | printk(KERN_EMERG "Machine check: %s\n", exp); | ||
277 | if (panic_timeout == 0) | ||
278 | panic_timeout = mce_panic_timeout; | ||
279 | panic(msg); | ||
280 | } | ||
281 | |||
282 | /* Support code for software error injection */ | ||
283 | |||
284 | static int msr_to_offset(u32 msr) | ||
285 | { | ||
286 | unsigned bank = __get_cpu_var(injectm.bank); | ||
287 | if (msr == rip_msr) | ||
288 | return offsetof(struct mce, ip); | ||
289 | if (msr == MSR_IA32_MC0_STATUS + bank*4) | ||
290 | return offsetof(struct mce, status); | ||
291 | if (msr == MSR_IA32_MC0_ADDR + bank*4) | ||
292 | return offsetof(struct mce, addr); | ||
293 | if (msr == MSR_IA32_MC0_MISC + bank*4) | ||
294 | return offsetof(struct mce, misc); | ||
295 | if (msr == MSR_IA32_MCG_STATUS) | ||
296 | return offsetof(struct mce, mcgstatus); | ||
297 | return -1; | ||
298 | } | ||
299 | |||
300 | /* MSR access wrappers used for error injection */ | ||
301 | static u64 mce_rdmsrl(u32 msr) | ||
302 | { | ||
303 | u64 v; | ||
304 | if (__get_cpu_var(injectm).finished) { | ||
305 | int offset = msr_to_offset(msr); | ||
306 | if (offset < 0) | ||
307 | return 0; | ||
308 | return *(u64 *)((char *)&__get_cpu_var(injectm) + offset); | ||
309 | } | ||
310 | rdmsrl(msr, v); | ||
311 | return v; | ||
312 | } | ||
313 | |||
314 | static void mce_wrmsrl(u32 msr, u64 v) | ||
315 | { | ||
316 | if (__get_cpu_var(injectm).finished) { | ||
317 | int offset = msr_to_offset(msr); | ||
318 | if (offset >= 0) | ||
319 | *(u64 *)((char *)&__get_cpu_var(injectm) + offset) = v; | ||
320 | return; | ||
321 | } | ||
322 | wrmsrl(msr, v); | ||
323 | } | ||
324 | |||
325 | /* | ||
326 | * Simple lockless ring to communicate PFNs from the exception handler with the | ||
327 | * process context work function. This is vastly simplified because there's | ||
328 | * only a single reader and a single writer. | ||
329 | */ | ||
330 | #define MCE_RING_SIZE 16 /* we use one entry less */ | ||
331 | |||
332 | struct mce_ring { | ||
333 | unsigned short start; | ||
334 | unsigned short end; | ||
335 | unsigned long ring[MCE_RING_SIZE]; | ||
336 | }; | ||
337 | static DEFINE_PER_CPU(struct mce_ring, mce_ring); | ||
338 | |||
339 | /* Runs with CPU affinity in workqueue */ | ||
340 | static int mce_ring_empty(void) | ||
341 | { | ||
342 | struct mce_ring *r = &__get_cpu_var(mce_ring); | ||
343 | |||
344 | return r->start == r->end; | ||
345 | } | ||
346 | |||
347 | static int mce_ring_get(unsigned long *pfn) | ||
348 | { | ||
349 | struct mce_ring *r; | ||
350 | int ret = 0; | ||
351 | |||
352 | *pfn = 0; | ||
353 | get_cpu(); | ||
354 | r = &__get_cpu_var(mce_ring); | ||
355 | if (r->start == r->end) | ||
356 | goto out; | ||
357 | *pfn = r->ring[r->start]; | ||
358 | r->start = (r->start + 1) % MCE_RING_SIZE; | ||
359 | ret = 1; | ||
360 | out: | ||
361 | put_cpu(); | ||
362 | return ret; | ||
363 | } | ||
364 | |||
365 | /* Always runs in MCE context with preempt off */ | ||
366 | static int mce_ring_add(unsigned long pfn) | ||
367 | { | ||
368 | struct mce_ring *r = &__get_cpu_var(mce_ring); | ||
369 | unsigned next; | ||
370 | |||
371 | next = (r->end + 1) % MCE_RING_SIZE; | ||
372 | if (next == r->start) | ||
373 | return -1; | ||
374 | r->ring[r->end] = pfn; | ||
375 | wmb(); | ||
376 | r->end = next; | ||
377 | return 0; | ||
378 | } | ||
379 | |||
380 | int mce_available(struct cpuinfo_x86 *c) | ||
381 | { | ||
382 | if (mce_disabled) | ||
383 | return 0; | ||
384 | return cpu_has(c, X86_FEATURE_MCE) && cpu_has(c, X86_FEATURE_MCA); | ||
385 | } | ||
386 | |||
387 | static void mce_schedule_work(void) | ||
388 | { | ||
389 | if (!mce_ring_empty()) { | ||
390 | struct work_struct *work = &__get_cpu_var(mce_work); | ||
391 | if (!work_pending(work)) | ||
392 | schedule_work(work); | ||
393 | } | ||
394 | } | ||
395 | |||
396 | /* | ||
397 | * Get the address of the instruction at the time of the machine check | ||
398 | * error. | ||
399 | */ | ||
400 | static inline void mce_get_rip(struct mce *m, struct pt_regs *regs) | ||
401 | { | ||
402 | |||
403 | if (regs && (m->mcgstatus & (MCG_STATUS_RIPV|MCG_STATUS_EIPV))) { | ||
404 | m->ip = regs->ip; | ||
405 | m->cs = regs->cs; | ||
406 | } else { | ||
407 | m->ip = 0; | ||
408 | m->cs = 0; | ||
409 | } | ||
410 | if (rip_msr) | ||
411 | m->ip = mce_rdmsrl(rip_msr); | ||
412 | } | ||
413 | |||
414 | #ifdef CONFIG_X86_LOCAL_APIC | ||
415 | /* | ||
416 | * Called after interrupts have been reenabled again | ||
417 | * when a MCE happened during an interrupts off region | ||
418 | * in the kernel. | ||
419 | */ | ||
420 | asmlinkage void smp_mce_self_interrupt(struct pt_regs *regs) | ||
421 | { | ||
422 | ack_APIC_irq(); | ||
423 | exit_idle(); | ||
424 | irq_enter(); | ||
425 | mce_notify_irq(); | ||
426 | mce_schedule_work(); | ||
427 | irq_exit(); | ||
428 | } | ||
429 | #endif | ||
430 | |||
431 | static void mce_report_event(struct pt_regs *regs) | ||
432 | { | ||
433 | if (regs->flags & (X86_VM_MASK|X86_EFLAGS_IF)) { | ||
434 | mce_notify_irq(); | ||
435 | /* | ||
436 | * Triggering the work queue here is just an insurance | ||
437 | * policy in case the syscall exit notify handler | ||
438 | * doesn't run soon enough or ends up running on the | ||
439 | * wrong CPU (can happen when audit sleeps) | ||
440 | */ | ||
441 | mce_schedule_work(); | ||
442 | return; | ||
443 | } | ||
444 | |||
445 | #ifdef CONFIG_X86_LOCAL_APIC | ||
446 | /* | ||
447 | * Without APIC do not notify. The event will be picked | ||
448 | * up eventually. | ||
449 | */ | ||
450 | if (!cpu_has_apic) | ||
451 | return; | ||
452 | |||
453 | /* | ||
454 | * When interrupts are disabled we cannot use | ||
455 | * kernel services safely. Trigger an self interrupt | ||
456 | * through the APIC to instead do the notification | ||
457 | * after interrupts are reenabled again. | ||
458 | */ | ||
459 | apic->send_IPI_self(MCE_SELF_VECTOR); | ||
460 | |||
461 | /* | ||
462 | * Wait for idle afterwards again so that we don't leave the | ||
463 | * APIC in a non idle state because the normal APIC writes | ||
464 | * cannot exclude us. | ||
465 | */ | ||
466 | apic_wait_icr_idle(); | ||
467 | #endif | ||
468 | } | ||
469 | |||
470 | DEFINE_PER_CPU(unsigned, mce_poll_count); | ||
471 | |||
472 | /* | ||
473 | * Poll for corrected events or events that happened before reset. | ||
474 | * Those are just logged through /dev/mcelog. | ||
475 | * | ||
476 | * This is executed in standard interrupt context. | ||
477 | * | ||
478 | * Note: spec recommends to panic for fatal unsignalled | ||
479 | * errors here. However this would be quite problematic -- | ||
480 | * we would need to reimplement the Monarch handling and | ||
481 | * it would mess up the exclusion between exception handler | ||
482 | * and poll hander -- * so we skip this for now. | ||
483 | * These cases should not happen anyways, or only when the CPU | ||
484 | * is already totally * confused. In this case it's likely it will | ||
485 | * not fully execute the machine check handler either. | ||
486 | */ | ||
487 | void machine_check_poll(enum mcp_flags flags, mce_banks_t *b) | ||
488 | { | ||
489 | struct mce m; | ||
490 | int i; | ||
491 | |||
492 | __get_cpu_var(mce_poll_count)++; | ||
493 | |||
494 | mce_setup(&m); | ||
495 | |||
496 | m.mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS); | ||
497 | for (i = 0; i < banks; i++) { | ||
498 | if (!bank[i] || !test_bit(i, *b)) | ||
499 | continue; | ||
500 | |||
501 | m.misc = 0; | ||
502 | m.addr = 0; | ||
503 | m.bank = i; | ||
504 | m.tsc = 0; | ||
505 | |||
506 | barrier(); | ||
507 | m.status = mce_rdmsrl(MSR_IA32_MC0_STATUS + i*4); | ||
508 | if (!(m.status & MCI_STATUS_VAL)) | ||
509 | continue; | ||
510 | |||
511 | /* | ||
512 | * Uncorrected or signalled events are handled by the exception | ||
513 | * handler when it is enabled, so don't process those here. | ||
514 | * | ||
515 | * TBD do the same check for MCI_STATUS_EN here? | ||
516 | */ | ||
517 | if (!(flags & MCP_UC) && | ||
518 | (m.status & (mce_ser ? MCI_STATUS_S : MCI_STATUS_UC))) | ||
519 | continue; | ||
520 | |||
521 | if (m.status & MCI_STATUS_MISCV) | ||
522 | m.misc = mce_rdmsrl(MSR_IA32_MC0_MISC + i*4); | ||
523 | if (m.status & MCI_STATUS_ADDRV) | ||
524 | m.addr = mce_rdmsrl(MSR_IA32_MC0_ADDR + i*4); | ||
525 | |||
526 | if (!(flags & MCP_TIMESTAMP)) | ||
527 | m.tsc = 0; | ||
528 | /* | ||
529 | * Don't get the IP here because it's unlikely to | ||
530 | * have anything to do with the actual error location. | ||
531 | */ | ||
532 | if (!(flags & MCP_DONTLOG) && !mce_dont_log_ce) { | ||
533 | mce_log(&m); | ||
534 | add_taint(TAINT_MACHINE_CHECK); | ||
535 | } | ||
536 | |||
537 | /* | ||
538 | * Clear state for this bank. | ||
539 | */ | ||
540 | mce_wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0); | ||
541 | } | ||
542 | |||
543 | /* | ||
544 | * Don't clear MCG_STATUS here because it's only defined for | ||
545 | * exceptions. | ||
546 | */ | ||
547 | |||
548 | sync_core(); | ||
549 | } | ||
550 | EXPORT_SYMBOL_GPL(machine_check_poll); | ||
551 | |||
552 | /* | ||
553 | * Do a quick check if any of the events requires a panic. | ||
554 | * This decides if we keep the events around or clear them. | ||
555 | */ | ||
556 | static int mce_no_way_out(struct mce *m, char **msg) | ||
557 | { | ||
558 | int i; | ||
559 | |||
560 | for (i = 0; i < banks; i++) { | ||
561 | m->status = mce_rdmsrl(MSR_IA32_MC0_STATUS + i*4); | ||
562 | if (mce_severity(m, tolerant, msg) >= MCE_PANIC_SEVERITY) | ||
563 | return 1; | ||
564 | } | ||
565 | return 0; | ||
566 | } | ||
567 | |||
568 | /* | ||
569 | * Variable to establish order between CPUs while scanning. | ||
570 | * Each CPU spins initially until executing is equal its number. | ||
571 | */ | ||
572 | static atomic_t mce_executing; | ||
573 | |||
574 | /* | ||
575 | * Defines order of CPUs on entry. First CPU becomes Monarch. | ||
576 | */ | ||
577 | static atomic_t mce_callin; | ||
578 | |||
579 | /* | ||
580 | * Check if a timeout waiting for other CPUs happened. | ||
581 | */ | ||
582 | static int mce_timed_out(u64 *t) | ||
583 | { | ||
584 | /* | ||
585 | * The others already did panic for some reason. | ||
586 | * Bail out like in a timeout. | ||
587 | * rmb() to tell the compiler that system_state | ||
588 | * might have been modified by someone else. | ||
589 | */ | ||
590 | rmb(); | ||
591 | if (atomic_read(&mce_paniced)) | ||
592 | wait_for_panic(); | ||
593 | if (!monarch_timeout) | ||
594 | goto out; | ||
595 | if ((s64)*t < SPINUNIT) { | ||
596 | /* CHECKME: Make panic default for 1 too? */ | ||
597 | if (tolerant < 1) | ||
598 | mce_panic("Timeout synchronizing machine check over CPUs", | ||
599 | NULL, NULL); | ||
600 | cpu_missing = 1; | ||
601 | return 1; | ||
602 | } | ||
603 | *t -= SPINUNIT; | ||
604 | out: | ||
605 | touch_nmi_watchdog(); | ||
606 | return 0; | ||
607 | } | ||
608 | |||
609 | /* | ||
610 | * The Monarch's reign. The Monarch is the CPU who entered | ||
611 | * the machine check handler first. It waits for the others to | ||
612 | * raise the exception too and then grades them. When any | ||
613 | * error is fatal panic. Only then let the others continue. | ||
614 | * | ||
615 | * The other CPUs entering the MCE handler will be controlled by the | ||
616 | * Monarch. They are called Subjects. | ||
617 | * | ||
618 | * This way we prevent any potential data corruption in a unrecoverable case | ||
619 | * and also makes sure always all CPU's errors are examined. | ||
620 | * | ||
621 | * Also this detects the case of an machine check event coming from outer | ||
622 | * space (not detected by any CPUs) In this case some external agent wants | ||
623 | * us to shut down, so panic too. | ||
624 | * | ||
625 | * The other CPUs might still decide to panic if the handler happens | ||
626 | * in a unrecoverable place, but in this case the system is in a semi-stable | ||
627 | * state and won't corrupt anything by itself. It's ok to let the others | ||
628 | * continue for a bit first. | ||
629 | * | ||
630 | * All the spin loops have timeouts; when a timeout happens a CPU | ||
631 | * typically elects itself to be Monarch. | ||
632 | */ | ||
633 | static void mce_reign(void) | ||
634 | { | ||
635 | int cpu; | ||
636 | struct mce *m = NULL; | ||
637 | int global_worst = 0; | ||
638 | char *msg = NULL; | ||
639 | char *nmsg = NULL; | ||
640 | |||
641 | /* | ||
642 | * This CPU is the Monarch and the other CPUs have run | ||
643 | * through their handlers. | ||
644 | * Grade the severity of the errors of all the CPUs. | ||
645 | */ | ||
646 | for_each_possible_cpu(cpu) { | ||
647 | int severity = mce_severity(&per_cpu(mces_seen, cpu), tolerant, | ||
648 | &nmsg); | ||
649 | if (severity > global_worst) { | ||
650 | msg = nmsg; | ||
651 | global_worst = severity; | ||
652 | m = &per_cpu(mces_seen, cpu); | ||
653 | } | ||
654 | } | ||
655 | |||
656 | /* | ||
657 | * Cannot recover? Panic here then. | ||
658 | * This dumps all the mces in the log buffer and stops the | ||
659 | * other CPUs. | ||
660 | */ | ||
661 | if (m && global_worst >= MCE_PANIC_SEVERITY && tolerant < 3) | ||
662 | mce_panic("Fatal Machine check", m, msg); | ||
663 | |||
664 | /* | ||
665 | * For UC somewhere we let the CPU who detects it handle it. | ||
666 | * Also must let continue the others, otherwise the handling | ||
667 | * CPU could deadlock on a lock. | ||
668 | */ | ||
669 | |||
670 | /* | ||
671 | * No machine check event found. Must be some external | ||
672 | * source or one CPU is hung. Panic. | ||
673 | */ | ||
674 | if (!m && tolerant < 3) | ||
675 | mce_panic("Machine check from unknown source", NULL, NULL); | ||
676 | |||
677 | /* | ||
678 | * Now clear all the mces_seen so that they don't reappear on | ||
679 | * the next mce. | ||
680 | */ | ||
681 | for_each_possible_cpu(cpu) | ||
682 | memset(&per_cpu(mces_seen, cpu), 0, sizeof(struct mce)); | ||
683 | } | ||
684 | |||
685 | static atomic_t global_nwo; | ||
686 | |||
687 | /* | ||
688 | * Start of Monarch synchronization. This waits until all CPUs have | ||
689 | * entered the exception handler and then determines if any of them | ||
690 | * saw a fatal event that requires panic. Then it executes them | ||
691 | * in the entry order. | ||
692 | * TBD double check parallel CPU hotunplug | ||
693 | */ | ||
694 | static int mce_start(int no_way_out, int *order) | ||
695 | { | ||
696 | int nwo; | ||
697 | int cpus = num_online_cpus(); | ||
698 | u64 timeout = (u64)monarch_timeout * NSEC_PER_USEC; | ||
699 | |||
700 | if (!timeout) { | ||
701 | *order = -1; | ||
702 | return no_way_out; | ||
703 | } | ||
704 | |||
705 | atomic_add(no_way_out, &global_nwo); | ||
706 | |||
707 | /* | ||
708 | * Wait for everyone. | ||
709 | */ | ||
710 | while (atomic_read(&mce_callin) != cpus) { | ||
711 | if (mce_timed_out(&timeout)) { | ||
712 | atomic_set(&global_nwo, 0); | ||
713 | *order = -1; | ||
714 | return no_way_out; | ||
715 | } | ||
716 | ndelay(SPINUNIT); | ||
717 | } | ||
718 | |||
719 | /* | ||
720 | * Cache the global no_way_out state. | ||
721 | */ | ||
722 | nwo = atomic_read(&global_nwo); | ||
723 | |||
724 | /* | ||
725 | * Monarch starts executing now, the others wait. | ||
726 | */ | ||
727 | if (*order == 1) { | ||
728 | atomic_set(&mce_executing, 1); | ||
729 | return nwo; | ||
730 | } | ||
731 | |||
732 | /* | ||
733 | * Now start the scanning loop one by one | ||
734 | * in the original callin order. | ||
735 | * This way when there are any shared banks it will | ||
736 | * be only seen by one CPU before cleared, avoiding duplicates. | ||
737 | */ | ||
738 | while (atomic_read(&mce_executing) < *order) { | ||
739 | if (mce_timed_out(&timeout)) { | ||
740 | atomic_set(&global_nwo, 0); | ||
741 | *order = -1; | ||
742 | return no_way_out; | ||
743 | } | ||
744 | ndelay(SPINUNIT); | ||
745 | } | ||
746 | return nwo; | ||
747 | } | ||
748 | |||
749 | /* | ||
750 | * Synchronize between CPUs after main scanning loop. | ||
751 | * This invokes the bulk of the Monarch processing. | ||
752 | */ | ||
753 | static int mce_end(int order) | ||
754 | { | ||
755 | int ret = -1; | ||
756 | u64 timeout = (u64)monarch_timeout * NSEC_PER_USEC; | ||
757 | |||
758 | if (!timeout) | ||
759 | goto reset; | ||
760 | if (order < 0) | ||
761 | goto reset; | ||
762 | |||
763 | /* | ||
764 | * Allow others to run. | ||
765 | */ | ||
766 | atomic_inc(&mce_executing); | ||
767 | |||
768 | if (order == 1) { | ||
769 | /* CHECKME: Can this race with a parallel hotplug? */ | ||
770 | int cpus = num_online_cpus(); | ||
771 | |||
772 | /* | ||
773 | * Monarch: Wait for everyone to go through their scanning | ||
774 | * loops. | ||
775 | */ | ||
776 | while (atomic_read(&mce_executing) <= cpus) { | ||
777 | if (mce_timed_out(&timeout)) | ||
778 | goto reset; | ||
779 | ndelay(SPINUNIT); | ||
780 | } | ||
781 | |||
782 | mce_reign(); | ||
783 | barrier(); | ||
784 | ret = 0; | ||
785 | } else { | ||
786 | /* | ||
787 | * Subject: Wait for Monarch to finish. | ||
788 | */ | ||
789 | while (atomic_read(&mce_executing) != 0) { | ||
790 | if (mce_timed_out(&timeout)) | ||
791 | goto reset; | ||
792 | ndelay(SPINUNIT); | ||
793 | } | ||
794 | |||
795 | /* | ||
796 | * Don't reset anything. That's done by the Monarch. | ||
797 | */ | ||
798 | return 0; | ||
799 | } | ||
800 | |||
801 | /* | ||
802 | * Reset all global state. | ||
803 | */ | ||
804 | reset: | ||
805 | atomic_set(&global_nwo, 0); | ||
806 | atomic_set(&mce_callin, 0); | ||
807 | barrier(); | ||
808 | |||
809 | /* | ||
810 | * Let others run again. | ||
811 | */ | ||
812 | atomic_set(&mce_executing, 0); | ||
813 | return ret; | ||
814 | } | ||
815 | |||
816 | /* | ||
817 | * Check if the address reported by the CPU is in a format we can parse. | ||
818 | * It would be possible to add code for most other cases, but all would | ||
819 | * be somewhat complicated (e.g. segment offset would require an instruction | ||
820 | * parser). So only support physical addresses upto page granuality for now. | ||
821 | */ | ||
822 | static int mce_usable_address(struct mce *m) | ||
823 | { | ||
824 | if (!(m->status & MCI_STATUS_MISCV) || !(m->status & MCI_STATUS_ADDRV)) | ||
825 | return 0; | ||
826 | if ((m->misc & 0x3f) > PAGE_SHIFT) | ||
827 | return 0; | ||
828 | if (((m->misc >> 6) & 7) != MCM_ADDR_PHYS) | ||
829 | return 0; | ||
830 | return 1; | ||
831 | } | ||
832 | |||
833 | static void mce_clear_state(unsigned long *toclear) | ||
834 | { | ||
835 | int i; | ||
836 | |||
837 | for (i = 0; i < banks; i++) { | ||
838 | if (test_bit(i, toclear)) | ||
839 | mce_wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0); | ||
840 | } | ||
841 | } | ||
842 | |||
843 | /* | ||
844 | * The actual machine check handler. This only handles real | ||
845 | * exceptions when something got corrupted coming in through int 18. | ||
846 | * | ||
847 | * This is executed in NMI context not subject to normal locking rules. This | ||
848 | * implies that most kernel services cannot be safely used. Don't even | ||
849 | * think about putting a printk in there! | ||
850 | * | ||
851 | * On Intel systems this is entered on all CPUs in parallel through | ||
852 | * MCE broadcast. However some CPUs might be broken beyond repair, | ||
853 | * so be always careful when synchronizing with others. | ||
854 | */ | ||
855 | void do_machine_check(struct pt_regs *regs, long error_code) | ||
856 | { | ||
857 | struct mce m, *final; | ||
858 | int i; | ||
859 | int worst = 0; | ||
860 | int severity; | ||
861 | /* | ||
862 | * Establish sequential order between the CPUs entering the machine | ||
863 | * check handler. | ||
864 | */ | ||
865 | int order; | ||
866 | |||
867 | /* | ||
868 | * If no_way_out gets set, there is no safe way to recover from this | ||
869 | * MCE. If tolerant is cranked up, we'll try anyway. | ||
870 | */ | ||
871 | int no_way_out = 0; | ||
872 | /* | ||
873 | * If kill_it gets set, there might be a way to recover from this | ||
874 | * error. | ||
875 | */ | ||
876 | int kill_it = 0; | ||
877 | DECLARE_BITMAP(toclear, MAX_NR_BANKS); | ||
878 | char *msg = "Unknown"; | ||
879 | |||
880 | atomic_inc(&mce_entry); | ||
881 | |||
882 | __get_cpu_var(mce_exception_count)++; | ||
883 | |||
884 | if (notify_die(DIE_NMI, "machine check", regs, error_code, | ||
885 | 18, SIGKILL) == NOTIFY_STOP) | ||
886 | goto out; | ||
887 | if (!banks) | ||
888 | goto out; | ||
889 | |||
890 | order = atomic_add_return(1, &mce_callin); | ||
891 | mce_setup(&m); | ||
892 | |||
893 | m.mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS); | ||
894 | no_way_out = mce_no_way_out(&m, &msg); | ||
895 | |||
896 | final = &__get_cpu_var(mces_seen); | ||
897 | *final = m; | ||
898 | |||
899 | barrier(); | ||
900 | |||
901 | /* | ||
902 | * When no restart IP must always kill or panic. | ||
903 | */ | ||
904 | if (!(m.mcgstatus & MCG_STATUS_RIPV)) | ||
905 | kill_it = 1; | ||
906 | |||
907 | /* | ||
908 | * Go through all the banks in exclusion of the other CPUs. | ||
909 | * This way we don't report duplicated events on shared banks | ||
910 | * because the first one to see it will clear it. | ||
911 | */ | ||
912 | no_way_out = mce_start(no_way_out, &order); | ||
913 | for (i = 0; i < banks; i++) { | ||
914 | __clear_bit(i, toclear); | ||
915 | if (!bank[i]) | ||
916 | continue; | ||
917 | |||
918 | m.misc = 0; | ||
919 | m.addr = 0; | ||
920 | m.bank = i; | ||
921 | |||
922 | m.status = mce_rdmsrl(MSR_IA32_MC0_STATUS + i*4); | ||
923 | if ((m.status & MCI_STATUS_VAL) == 0) | ||
924 | continue; | ||
925 | |||
926 | /* | ||
927 | * Non uncorrected or non signaled errors are handled by | ||
928 | * machine_check_poll. Leave them alone, unless this panics. | ||
929 | */ | ||
930 | if (!(m.status & (mce_ser ? MCI_STATUS_S : MCI_STATUS_UC)) && | ||
931 | !no_way_out) | ||
932 | continue; | ||
933 | |||
934 | /* | ||
935 | * Set taint even when machine check was not enabled. | ||
936 | */ | ||
937 | add_taint(TAINT_MACHINE_CHECK); | ||
938 | |||
939 | severity = mce_severity(&m, tolerant, NULL); | ||
940 | |||
941 | /* | ||
942 | * When machine check was for corrected handler don't touch, | ||
943 | * unless we're panicing. | ||
944 | */ | ||
945 | if (severity == MCE_KEEP_SEVERITY && !no_way_out) | ||
946 | continue; | ||
947 | __set_bit(i, toclear); | ||
948 | if (severity == MCE_NO_SEVERITY) { | ||
949 | /* | ||
950 | * Machine check event was not enabled. Clear, but | ||
951 | * ignore. | ||
952 | */ | ||
953 | continue; | ||
954 | } | ||
955 | |||
956 | /* | ||
957 | * Kill on action required. | ||
958 | */ | ||
959 | if (severity == MCE_AR_SEVERITY) | ||
960 | kill_it = 1; | ||
961 | |||
962 | if (m.status & MCI_STATUS_MISCV) | ||
963 | m.misc = mce_rdmsrl(MSR_IA32_MC0_MISC + i*4); | ||
964 | if (m.status & MCI_STATUS_ADDRV) | ||
965 | m.addr = mce_rdmsrl(MSR_IA32_MC0_ADDR + i*4); | ||
966 | |||
967 | /* | ||
968 | * Action optional error. Queue address for later processing. | ||
969 | * When the ring overflows we just ignore the AO error. | ||
970 | * RED-PEN add some logging mechanism when | ||
971 | * usable_address or mce_add_ring fails. | ||
972 | * RED-PEN don't ignore overflow for tolerant == 0 | ||
973 | */ | ||
974 | if (severity == MCE_AO_SEVERITY && mce_usable_address(&m)) | ||
975 | mce_ring_add(m.addr >> PAGE_SHIFT); | ||
976 | |||
977 | mce_get_rip(&m, regs); | ||
978 | mce_log(&m); | ||
979 | |||
980 | if (severity > worst) { | ||
981 | *final = m; | ||
982 | worst = severity; | ||
983 | } | ||
984 | } | ||
985 | |||
986 | if (!no_way_out) | ||
987 | mce_clear_state(toclear); | ||
988 | |||
989 | /* | ||
990 | * Do most of the synchronization with other CPUs. | ||
991 | * When there's any problem use only local no_way_out state. | ||
992 | */ | ||
993 | if (mce_end(order) < 0) | ||
994 | no_way_out = worst >= MCE_PANIC_SEVERITY; | ||
995 | |||
996 | /* | ||
997 | * If we have decided that we just CAN'T continue, and the user | ||
998 | * has not set tolerant to an insane level, give up and die. | ||
999 | * | ||
1000 | * This is mainly used in the case when the system doesn't | ||
1001 | * support MCE broadcasting or it has been disabled. | ||
1002 | */ | ||
1003 | if (no_way_out && tolerant < 3) | ||
1004 | mce_panic("Fatal machine check on current CPU", final, msg); | ||
1005 | |||
1006 | /* | ||
1007 | * If the error seems to be unrecoverable, something should be | ||
1008 | * done. Try to kill as little as possible. If we can kill just | ||
1009 | * one task, do that. If the user has set the tolerance very | ||
1010 | * high, don't try to do anything at all. | ||
1011 | */ | ||
1012 | |||
1013 | if (kill_it && tolerant < 3) | ||
1014 | force_sig(SIGBUS, current); | ||
1015 | |||
1016 | /* notify userspace ASAP */ | ||
1017 | set_thread_flag(TIF_MCE_NOTIFY); | ||
1018 | |||
1019 | if (worst > 0) | ||
1020 | mce_report_event(regs); | ||
1021 | mce_wrmsrl(MSR_IA32_MCG_STATUS, 0); | ||
1022 | out: | ||
1023 | atomic_dec(&mce_entry); | ||
1024 | sync_core(); | ||
1025 | } | ||
1026 | EXPORT_SYMBOL_GPL(do_machine_check); | ||
1027 | |||
1028 | /* dummy to break dependency. actual code is in mm/memory-failure.c */ | ||
1029 | void __attribute__((weak)) memory_failure(unsigned long pfn, int vector) | ||
1030 | { | ||
1031 | printk(KERN_ERR "Action optional memory failure at %lx ignored\n", pfn); | ||
1032 | } | ||
1033 | |||
1034 | /* | ||
1035 | * Called after mce notification in process context. This code | ||
1036 | * is allowed to sleep. Call the high level VM handler to process | ||
1037 | * any corrupted pages. | ||
1038 | * Assume that the work queue code only calls this one at a time | ||
1039 | * per CPU. | ||
1040 | * Note we don't disable preemption, so this code might run on the wrong | ||
1041 | * CPU. In this case the event is picked up by the scheduled work queue. | ||
1042 | * This is merely a fast path to expedite processing in some common | ||
1043 | * cases. | ||
1044 | */ | ||
1045 | void mce_notify_process(void) | ||
1046 | { | ||
1047 | unsigned long pfn; | ||
1048 | mce_notify_irq(); | ||
1049 | while (mce_ring_get(&pfn)) | ||
1050 | memory_failure(pfn, MCE_VECTOR); | ||
1051 | } | ||
1052 | |||
1053 | static void mce_process_work(struct work_struct *dummy) | ||
1054 | { | ||
1055 | mce_notify_process(); | ||
1056 | } | ||
1057 | |||
1058 | #ifdef CONFIG_X86_MCE_INTEL | ||
1059 | /*** | ||
1060 | * mce_log_therm_throt_event - Logs the thermal throttling event to mcelog | ||
1061 | * @cpu: The CPU on which the event occurred. | ||
1062 | * @status: Event status information | ||
1063 | * | ||
1064 | * This function should be called by the thermal interrupt after the | ||
1065 | * event has been processed and the decision was made to log the event | ||
1066 | * further. | ||
1067 | * | ||
1068 | * The status parameter will be saved to the 'status' field of 'struct mce' | ||
1069 | * and historically has been the register value of the | ||
1070 | * MSR_IA32_THERMAL_STATUS (Intel) msr. | ||
1071 | */ | ||
1072 | void mce_log_therm_throt_event(__u64 status) | ||
1073 | { | ||
1074 | struct mce m; | ||
1075 | |||
1076 | mce_setup(&m); | ||
1077 | m.bank = MCE_THERMAL_BANK; | ||
1078 | m.status = status; | ||
1079 | mce_log(&m); | ||
1080 | } | ||
1081 | #endif /* CONFIG_X86_MCE_INTEL */ | ||
1082 | |||
1083 | /* | ||
1084 | * Periodic polling timer for "silent" machine check errors. If the | ||
1085 | * poller finds an MCE, poll 2x faster. When the poller finds no more | ||
1086 | * errors, poll 2x slower (up to check_interval seconds). | ||
1087 | */ | ||
1088 | static int check_interval = 5 * 60; /* 5 minutes */ | ||
1089 | |||
1090 | static DEFINE_PER_CPU(int, next_interval); /* in jiffies */ | ||
1091 | static DEFINE_PER_CPU(struct timer_list, mce_timer); | ||
1092 | |||
1093 | static void mcheck_timer(unsigned long data) | ||
1094 | { | ||
1095 | struct timer_list *t = &per_cpu(mce_timer, data); | ||
1096 | int *n; | ||
1097 | |||
1098 | WARN_ON(smp_processor_id() != data); | ||
1099 | |||
1100 | if (mce_available(¤t_cpu_data)) { | ||
1101 | machine_check_poll(MCP_TIMESTAMP, | ||
1102 | &__get_cpu_var(mce_poll_banks)); | ||
1103 | } | ||
1104 | |||
1105 | /* | ||
1106 | * Alert userspace if needed. If we logged an MCE, reduce the | ||
1107 | * polling interval, otherwise increase the polling interval. | ||
1108 | */ | ||
1109 | n = &__get_cpu_var(next_interval); | ||
1110 | if (mce_notify_irq()) | ||
1111 | *n = max(*n/2, HZ/100); | ||
1112 | else | ||
1113 | *n = min(*n*2, (int)round_jiffies_relative(check_interval*HZ)); | ||
1114 | |||
1115 | t->expires = jiffies + *n; | ||
1116 | add_timer(t); | ||
1117 | } | ||
1118 | |||
1119 | static void mce_do_trigger(struct work_struct *work) | ||
1120 | { | ||
1121 | call_usermodehelper(trigger, trigger_argv, NULL, UMH_NO_WAIT); | ||
1122 | } | ||
1123 | |||
1124 | static DECLARE_WORK(mce_trigger_work, mce_do_trigger); | ||
1125 | |||
1126 | /* | ||
1127 | * Notify the user(s) about new machine check events. | ||
1128 | * Can be called from interrupt context, but not from machine check/NMI | ||
1129 | * context. | ||
1130 | */ | ||
1131 | int mce_notify_irq(void) | ||
1132 | { | ||
1133 | /* Not more than two messages every minute */ | ||
1134 | static DEFINE_RATELIMIT_STATE(ratelimit, 60*HZ, 2); | ||
1135 | |||
1136 | clear_thread_flag(TIF_MCE_NOTIFY); | ||
1137 | |||
1138 | if (test_and_clear_bit(0, ¬ify_user)) { | ||
1139 | wake_up_interruptible(&mce_wait); | ||
1140 | |||
1141 | /* | ||
1142 | * There is no risk of missing notifications because | ||
1143 | * work_pending is always cleared before the function is | ||
1144 | * executed. | ||
1145 | */ | ||
1146 | if (trigger[0] && !work_pending(&mce_trigger_work)) | ||
1147 | schedule_work(&mce_trigger_work); | ||
1148 | |||
1149 | if (__ratelimit(&ratelimit)) | ||
1150 | printk(KERN_INFO "Machine check events logged\n"); | ||
1151 | |||
1152 | return 1; | ||
1153 | } | ||
1154 | return 0; | ||
1155 | } | ||
1156 | EXPORT_SYMBOL_GPL(mce_notify_irq); | ||
1157 | |||
1158 | /* | ||
1159 | * Initialize Machine Checks for a CPU. | ||
1160 | */ | ||
1161 | static int mce_cap_init(void) | ||
1162 | { | ||
1163 | unsigned b; | ||
1164 | u64 cap; | ||
1165 | |||
1166 | rdmsrl(MSR_IA32_MCG_CAP, cap); | ||
1167 | |||
1168 | b = cap & MCG_BANKCNT_MASK; | ||
1169 | printk(KERN_INFO "mce: CPU supports %d MCE banks\n", b); | ||
1170 | |||
1171 | if (b > MAX_NR_BANKS) { | ||
1172 | printk(KERN_WARNING | ||
1173 | "MCE: Using only %u machine check banks out of %u\n", | ||
1174 | MAX_NR_BANKS, b); | ||
1175 | b = MAX_NR_BANKS; | ||
1176 | } | ||
1177 | |||
1178 | /* Don't support asymmetric configurations today */ | ||
1179 | WARN_ON(banks != 0 && b != banks); | ||
1180 | banks = b; | ||
1181 | if (!bank) { | ||
1182 | bank = kmalloc(banks * sizeof(u64), GFP_KERNEL); | ||
1183 | if (!bank) | ||
1184 | return -ENOMEM; | ||
1185 | memset(bank, 0xff, banks * sizeof(u64)); | ||
1186 | } | ||
1187 | |||
1188 | /* Use accurate RIP reporting if available. */ | ||
1189 | if ((cap & MCG_EXT_P) && MCG_EXT_CNT(cap) >= 9) | ||
1190 | rip_msr = MSR_IA32_MCG_EIP; | ||
1191 | |||
1192 | if (cap & MCG_SER_P) | ||
1193 | mce_ser = 1; | ||
1194 | |||
1195 | return 0; | ||
1196 | } | ||
1197 | |||
1198 | static void mce_init(void) | ||
1199 | { | ||
1200 | mce_banks_t all_banks; | ||
1201 | u64 cap; | ||
1202 | int i; | ||
1203 | |||
1204 | /* | ||
1205 | * Log the machine checks left over from the previous reset. | ||
1206 | */ | ||
1207 | bitmap_fill(all_banks, MAX_NR_BANKS); | ||
1208 | machine_check_poll(MCP_UC|(!mce_bootlog ? MCP_DONTLOG : 0), &all_banks); | ||
1209 | |||
1210 | set_in_cr4(X86_CR4_MCE); | ||
1211 | |||
1212 | rdmsrl(MSR_IA32_MCG_CAP, cap); | ||
1213 | if (cap & MCG_CTL_P) | ||
1214 | wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff); | ||
1215 | |||
1216 | for (i = 0; i < banks; i++) { | ||
1217 | if (skip_bank_init(i)) | ||
1218 | continue; | ||
1219 | wrmsrl(MSR_IA32_MC0_CTL+4*i, bank[i]); | ||
1220 | wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0); | ||
1221 | } | ||
1222 | } | ||
1223 | |||
1224 | /* Add per CPU specific workarounds here */ | ||
1225 | static void mce_cpu_quirks(struct cpuinfo_x86 *c) | ||
1226 | { | ||
1227 | /* This should be disabled by the BIOS, but isn't always */ | ||
1228 | if (c->x86_vendor == X86_VENDOR_AMD) { | ||
1229 | if (c->x86 == 15 && banks > 4) { | ||
1230 | /* | ||
1231 | * disable GART TBL walk error reporting, which | ||
1232 | * trips off incorrectly with the IOMMU & 3ware | ||
1233 | * & Cerberus: | ||
1234 | */ | ||
1235 | clear_bit(10, (unsigned long *)&bank[4]); | ||
1236 | } | ||
1237 | if (c->x86 <= 17 && mce_bootlog < 0) { | ||
1238 | /* | ||
1239 | * Lots of broken BIOS around that don't clear them | ||
1240 | * by default and leave crap in there. Don't log: | ||
1241 | */ | ||
1242 | mce_bootlog = 0; | ||
1243 | } | ||
1244 | /* | ||
1245 | * Various K7s with broken bank 0 around. Always disable | ||
1246 | * by default. | ||
1247 | */ | ||
1248 | if (c->x86 == 6) | ||
1249 | bank[0] = 0; | ||
1250 | } | ||
1251 | |||
1252 | if (c->x86_vendor == X86_VENDOR_INTEL) { | ||
1253 | /* | ||
1254 | * SDM documents that on family 6 bank 0 should not be written | ||
1255 | * because it aliases to another special BIOS controlled | ||
1256 | * register. | ||
1257 | * But it's not aliased anymore on model 0x1a+ | ||
1258 | * Don't ignore bank 0 completely because there could be a | ||
1259 | * valid event later, merely don't write CTL0. | ||
1260 | */ | ||
1261 | |||
1262 | if (c->x86 == 6 && c->x86_model < 0x1A) | ||
1263 | __set_bit(0, &dont_init_banks); | ||
1264 | |||
1265 | /* | ||
1266 | * All newer Intel systems support MCE broadcasting. Enable | ||
1267 | * synchronization with a one second timeout. | ||
1268 | */ | ||
1269 | if ((c->x86 > 6 || (c->x86 == 6 && c->x86_model >= 0xe)) && | ||
1270 | monarch_timeout < 0) | ||
1271 | monarch_timeout = USEC_PER_SEC; | ||
1272 | } | ||
1273 | if (monarch_timeout < 0) | ||
1274 | monarch_timeout = 0; | ||
1275 | if (mce_bootlog != 0) | ||
1276 | mce_panic_timeout = 30; | ||
1277 | } | ||
1278 | |||
1279 | static void __cpuinit mce_ancient_init(struct cpuinfo_x86 *c) | ||
1280 | { | ||
1281 | if (c->x86 != 5) | ||
1282 | return; | ||
1283 | switch (c->x86_vendor) { | ||
1284 | case X86_VENDOR_INTEL: | ||
1285 | if (mce_p5_enabled()) | ||
1286 | intel_p5_mcheck_init(c); | ||
1287 | break; | ||
1288 | case X86_VENDOR_CENTAUR: | ||
1289 | winchip_mcheck_init(c); | ||
1290 | break; | ||
1291 | } | ||
1292 | } | ||
1293 | |||
1294 | static void mce_cpu_features(struct cpuinfo_x86 *c) | ||
1295 | { | ||
1296 | switch (c->x86_vendor) { | ||
1297 | case X86_VENDOR_INTEL: | ||
1298 | mce_intel_feature_init(c); | ||
1299 | break; | ||
1300 | case X86_VENDOR_AMD: | ||
1301 | mce_amd_feature_init(c); | ||
1302 | break; | ||
1303 | default: | ||
1304 | break; | ||
1305 | } | ||
1306 | } | ||
1307 | |||
1308 | static void mce_init_timer(void) | ||
1309 | { | ||
1310 | struct timer_list *t = &__get_cpu_var(mce_timer); | ||
1311 | int *n = &__get_cpu_var(next_interval); | ||
1312 | |||
1313 | if (mce_ignore_ce) | ||
1314 | return; | ||
1315 | |||
1316 | *n = check_interval * HZ; | ||
1317 | if (!*n) | ||
1318 | return; | ||
1319 | setup_timer(t, mcheck_timer, smp_processor_id()); | ||
1320 | t->expires = round_jiffies(jiffies + *n); | ||
1321 | add_timer(t); | ||
1322 | } | ||
1323 | |||
1324 | /* | ||
1325 | * Called for each booted CPU to set up machine checks. | ||
1326 | * Must be called with preempt off: | ||
1327 | */ | ||
1328 | void __cpuinit mcheck_init(struct cpuinfo_x86 *c) | ||
1329 | { | ||
1330 | if (mce_disabled) | ||
1331 | return; | ||
1332 | |||
1333 | mce_ancient_init(c); | ||
1334 | |||
1335 | if (!mce_available(c)) | ||
1336 | return; | ||
1337 | |||
1338 | if (mce_cap_init() < 0) { | ||
1339 | mce_disabled = 1; | ||
1340 | return; | ||
1341 | } | ||
1342 | mce_cpu_quirks(c); | ||
1343 | |||
1344 | machine_check_vector = do_machine_check; | ||
1345 | |||
1346 | mce_init(); | ||
1347 | mce_cpu_features(c); | ||
1348 | mce_init_timer(); | ||
1349 | INIT_WORK(&__get_cpu_var(mce_work), mce_process_work); | ||
1350 | } | ||
1351 | |||
1352 | /* | ||
1353 | * Character device to read and clear the MCE log. | ||
1354 | */ | ||
1355 | |||
1356 | static DEFINE_SPINLOCK(mce_state_lock); | ||
1357 | static int open_count; /* #times opened */ | ||
1358 | static int open_exclu; /* already open exclusive? */ | ||
1359 | |||
1360 | static int mce_open(struct inode *inode, struct file *file) | ||
1361 | { | ||
1362 | spin_lock(&mce_state_lock); | ||
1363 | |||
1364 | if (open_exclu || (open_count && (file->f_flags & O_EXCL))) { | ||
1365 | spin_unlock(&mce_state_lock); | ||
1366 | |||
1367 | return -EBUSY; | ||
1368 | } | ||
1369 | |||
1370 | if (file->f_flags & O_EXCL) | ||
1371 | open_exclu = 1; | ||
1372 | open_count++; | ||
1373 | |||
1374 | spin_unlock(&mce_state_lock); | ||
1375 | |||
1376 | return nonseekable_open(inode, file); | ||
1377 | } | ||
1378 | |||
1379 | static int mce_release(struct inode *inode, struct file *file) | ||
1380 | { | ||
1381 | spin_lock(&mce_state_lock); | ||
1382 | |||
1383 | open_count--; | ||
1384 | open_exclu = 0; | ||
1385 | |||
1386 | spin_unlock(&mce_state_lock); | ||
1387 | |||
1388 | return 0; | ||
1389 | } | ||
1390 | |||
1391 | static void collect_tscs(void *data) | ||
1392 | { | ||
1393 | unsigned long *cpu_tsc = (unsigned long *)data; | ||
1394 | |||
1395 | rdtscll(cpu_tsc[smp_processor_id()]); | ||
1396 | } | ||
1397 | |||
1398 | static DEFINE_MUTEX(mce_read_mutex); | ||
1399 | |||
1400 | static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize, | ||
1401 | loff_t *off) | ||
1402 | { | ||
1403 | char __user *buf = ubuf; | ||
1404 | unsigned long *cpu_tsc; | ||
1405 | unsigned prev, next; | ||
1406 | int i, err; | ||
1407 | |||
1408 | cpu_tsc = kmalloc(nr_cpu_ids * sizeof(long), GFP_KERNEL); | ||
1409 | if (!cpu_tsc) | ||
1410 | return -ENOMEM; | ||
1411 | |||
1412 | mutex_lock(&mce_read_mutex); | ||
1413 | next = rcu_dereference(mcelog.next); | ||
1414 | |||
1415 | /* Only supports full reads right now */ | ||
1416 | if (*off != 0 || usize < MCE_LOG_LEN*sizeof(struct mce)) { | ||
1417 | mutex_unlock(&mce_read_mutex); | ||
1418 | kfree(cpu_tsc); | ||
1419 | |||
1420 | return -EINVAL; | ||
1421 | } | ||
1422 | |||
1423 | err = 0; | ||
1424 | prev = 0; | ||
1425 | do { | ||
1426 | for (i = prev; i < next; i++) { | ||
1427 | unsigned long start = jiffies; | ||
1428 | |||
1429 | while (!mcelog.entry[i].finished) { | ||
1430 | if (time_after_eq(jiffies, start + 2)) { | ||
1431 | memset(mcelog.entry + i, 0, | ||
1432 | sizeof(struct mce)); | ||
1433 | goto timeout; | ||
1434 | } | ||
1435 | cpu_relax(); | ||
1436 | } | ||
1437 | smp_rmb(); | ||
1438 | err |= copy_to_user(buf, mcelog.entry + i, | ||
1439 | sizeof(struct mce)); | ||
1440 | buf += sizeof(struct mce); | ||
1441 | timeout: | ||
1442 | ; | ||
1443 | } | ||
1444 | |||
1445 | memset(mcelog.entry + prev, 0, | ||
1446 | (next - prev) * sizeof(struct mce)); | ||
1447 | prev = next; | ||
1448 | next = cmpxchg(&mcelog.next, prev, 0); | ||
1449 | } while (next != prev); | ||
1450 | |||
1451 | synchronize_sched(); | ||
1452 | |||
1453 | /* | ||
1454 | * Collect entries that were still getting written before the | ||
1455 | * synchronize. | ||
1456 | */ | ||
1457 | on_each_cpu(collect_tscs, cpu_tsc, 1); | ||
1458 | |||
1459 | for (i = next; i < MCE_LOG_LEN; i++) { | ||
1460 | if (mcelog.entry[i].finished && | ||
1461 | mcelog.entry[i].tsc < cpu_tsc[mcelog.entry[i].cpu]) { | ||
1462 | err |= copy_to_user(buf, mcelog.entry+i, | ||
1463 | sizeof(struct mce)); | ||
1464 | smp_rmb(); | ||
1465 | buf += sizeof(struct mce); | ||
1466 | memset(&mcelog.entry[i], 0, sizeof(struct mce)); | ||
1467 | } | ||
1468 | } | ||
1469 | mutex_unlock(&mce_read_mutex); | ||
1470 | kfree(cpu_tsc); | ||
1471 | |||
1472 | return err ? -EFAULT : buf - ubuf; | ||
1473 | } | ||
1474 | |||
1475 | static unsigned int mce_poll(struct file *file, poll_table *wait) | ||
1476 | { | ||
1477 | poll_wait(file, &mce_wait, wait); | ||
1478 | if (rcu_dereference(mcelog.next)) | ||
1479 | return POLLIN | POLLRDNORM; | ||
1480 | return 0; | ||
1481 | } | ||
1482 | |||
1483 | static long mce_ioctl(struct file *f, unsigned int cmd, unsigned long arg) | ||
1484 | { | ||
1485 | int __user *p = (int __user *)arg; | ||
1486 | |||
1487 | if (!capable(CAP_SYS_ADMIN)) | ||
1488 | return -EPERM; | ||
1489 | |||
1490 | switch (cmd) { | ||
1491 | case MCE_GET_RECORD_LEN: | ||
1492 | return put_user(sizeof(struct mce), p); | ||
1493 | case MCE_GET_LOG_LEN: | ||
1494 | return put_user(MCE_LOG_LEN, p); | ||
1495 | case MCE_GETCLEAR_FLAGS: { | ||
1496 | unsigned flags; | ||
1497 | |||
1498 | do { | ||
1499 | flags = mcelog.flags; | ||
1500 | } while (cmpxchg(&mcelog.flags, flags, 0) != flags); | ||
1501 | |||
1502 | return put_user(flags, p); | ||
1503 | } | ||
1504 | default: | ||
1505 | return -ENOTTY; | ||
1506 | } | ||
1507 | } | ||
1508 | |||
1509 | /* Modified in mce-inject.c, so not static or const */ | ||
1510 | struct file_operations mce_chrdev_ops = { | ||
1511 | .open = mce_open, | ||
1512 | .release = mce_release, | ||
1513 | .read = mce_read, | ||
1514 | .poll = mce_poll, | ||
1515 | .unlocked_ioctl = mce_ioctl, | ||
1516 | }; | ||
1517 | EXPORT_SYMBOL_GPL(mce_chrdev_ops); | ||
1518 | |||
1519 | static struct miscdevice mce_log_device = { | ||
1520 | MISC_MCELOG_MINOR, | ||
1521 | "mcelog", | ||
1522 | &mce_chrdev_ops, | ||
1523 | }; | ||
1524 | |||
1525 | /* | ||
1526 | * mce=off Disables machine check | ||
1527 | * mce=no_cmci Disables CMCI | ||
1528 | * mce=dont_log_ce Clears corrected events silently, no log created for CEs. | ||
1529 | * mce=ignore_ce Disables polling and CMCI, corrected events are not cleared. | ||
1530 | * mce=TOLERANCELEVEL[,monarchtimeout] (number, see above) | ||
1531 | * monarchtimeout is how long to wait for other CPUs on machine | ||
1532 | * check, or 0 to not wait | ||
1533 | * mce=bootlog Log MCEs from before booting. Disabled by default on AMD. | ||
1534 | * mce=nobootlog Don't log MCEs from before booting. | ||
1535 | */ | ||
1536 | static int __init mcheck_enable(char *str) | ||
1537 | { | ||
1538 | if (*str == 0) | ||
1539 | enable_p5_mce(); | ||
1540 | if (*str == '=') | ||
1541 | str++; | ||
1542 | if (!strcmp(str, "off")) | ||
1543 | mce_disabled = 1; | ||
1544 | else if (!strcmp(str, "no_cmci")) | ||
1545 | mce_cmci_disabled = 1; | ||
1546 | else if (!strcmp(str, "dont_log_ce")) | ||
1547 | mce_dont_log_ce = 1; | ||
1548 | else if (!strcmp(str, "ignore_ce")) | ||
1549 | mce_ignore_ce = 1; | ||
1550 | else if (!strcmp(str, "bootlog") || !strcmp(str, "nobootlog")) | ||
1551 | mce_bootlog = (str[0] == 'b'); | ||
1552 | else if (isdigit(str[0])) { | ||
1553 | get_option(&str, &tolerant); | ||
1554 | if (*str == ',') { | ||
1555 | ++str; | ||
1556 | get_option(&str, &monarch_timeout); | ||
1557 | } | ||
1558 | } else { | ||
1559 | printk(KERN_INFO "mce argument %s ignored. Please use /sys\n", | ||
1560 | str); | ||
1561 | return 0; | ||
1562 | } | ||
1563 | return 1; | ||
1564 | } | ||
1565 | __setup("mce", mcheck_enable); | ||
1566 | |||
1567 | /* | ||
1568 | * Sysfs support | ||
1569 | */ | ||
1570 | |||
1571 | /* | ||
1572 | * Disable machine checks on suspend and shutdown. We can't really handle | ||
1573 | * them later. | ||
1574 | */ | ||
1575 | static int mce_disable(void) | ||
1576 | { | ||
1577 | int i; | ||
1578 | |||
1579 | for (i = 0; i < banks; i++) { | ||
1580 | if (!skip_bank_init(i)) | ||
1581 | wrmsrl(MSR_IA32_MC0_CTL + i*4, 0); | ||
1582 | } | ||
1583 | return 0; | ||
1584 | } | ||
1585 | |||
1586 | static int mce_suspend(struct sys_device *dev, pm_message_t state) | ||
1587 | { | ||
1588 | return mce_disable(); | ||
1589 | } | ||
1590 | |||
1591 | static int mce_shutdown(struct sys_device *dev) | ||
1592 | { | ||
1593 | return mce_disable(); | ||
1594 | } | ||
1595 | |||
1596 | /* | ||
1597 | * On resume clear all MCE state. Don't want to see leftovers from the BIOS. | ||
1598 | * Only one CPU is active at this time, the others get re-added later using | ||
1599 | * CPU hotplug: | ||
1600 | */ | ||
1601 | static int mce_resume(struct sys_device *dev) | ||
1602 | { | ||
1603 | mce_init(); | ||
1604 | mce_cpu_features(¤t_cpu_data); | ||
1605 | |||
1606 | return 0; | ||
1607 | } | ||
1608 | |||
1609 | static void mce_cpu_restart(void *data) | ||
1610 | { | ||
1611 | del_timer_sync(&__get_cpu_var(mce_timer)); | ||
1612 | if (mce_available(¤t_cpu_data)) | ||
1613 | mce_init(); | ||
1614 | mce_init_timer(); | ||
1615 | } | ||
1616 | |||
1617 | /* Reinit MCEs after user configuration changes */ | ||
1618 | static void mce_restart(void) | ||
1619 | { | ||
1620 | on_each_cpu(mce_cpu_restart, NULL, 1); | ||
1621 | } | ||
1622 | |||
1623 | static struct sysdev_class mce_sysclass = { | ||
1624 | .suspend = mce_suspend, | ||
1625 | .shutdown = mce_shutdown, | ||
1626 | .resume = mce_resume, | ||
1627 | .name = "machinecheck", | ||
1628 | }; | ||
1629 | |||
1630 | DEFINE_PER_CPU(struct sys_device, mce_dev); | ||
1631 | |||
1632 | __cpuinitdata | ||
1633 | void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu); | ||
1634 | |||
1635 | static struct sysdev_attribute *bank_attrs; | ||
1636 | |||
1637 | static ssize_t show_bank(struct sys_device *s, struct sysdev_attribute *attr, | ||
1638 | char *buf) | ||
1639 | { | ||
1640 | u64 b = bank[attr - bank_attrs]; | ||
1641 | |||
1642 | return sprintf(buf, "%llx\n", b); | ||
1643 | } | ||
1644 | |||
1645 | static ssize_t set_bank(struct sys_device *s, struct sysdev_attribute *attr, | ||
1646 | const char *buf, size_t size) | ||
1647 | { | ||
1648 | u64 new; | ||
1649 | |||
1650 | if (strict_strtoull(buf, 0, &new) < 0) | ||
1651 | return -EINVAL; | ||
1652 | |||
1653 | bank[attr - bank_attrs] = new; | ||
1654 | mce_restart(); | ||
1655 | |||
1656 | return size; | ||
1657 | } | ||
1658 | |||
1659 | static ssize_t | ||
1660 | show_trigger(struct sys_device *s, struct sysdev_attribute *attr, char *buf) | ||
1661 | { | ||
1662 | strcpy(buf, trigger); | ||
1663 | strcat(buf, "\n"); | ||
1664 | return strlen(trigger) + 1; | ||
1665 | } | ||
1666 | |||
1667 | static ssize_t set_trigger(struct sys_device *s, struct sysdev_attribute *attr, | ||
1668 | const char *buf, size_t siz) | ||
1669 | { | ||
1670 | char *p; | ||
1671 | int len; | ||
1672 | |||
1673 | strncpy(trigger, buf, sizeof(trigger)); | ||
1674 | trigger[sizeof(trigger)-1] = 0; | ||
1675 | len = strlen(trigger); | ||
1676 | p = strchr(trigger, '\n'); | ||
1677 | |||
1678 | if (*p) | ||
1679 | *p = 0; | ||
1680 | |||
1681 | return len; | ||
1682 | } | ||
1683 | |||
1684 | static ssize_t store_int_with_restart(struct sys_device *s, | ||
1685 | struct sysdev_attribute *attr, | ||
1686 | const char *buf, size_t size) | ||
1687 | { | ||
1688 | ssize_t ret = sysdev_store_int(s, attr, buf, size); | ||
1689 | mce_restart(); | ||
1690 | return ret; | ||
1691 | } | ||
1692 | |||
1693 | static SYSDEV_ATTR(trigger, 0644, show_trigger, set_trigger); | ||
1694 | static SYSDEV_INT_ATTR(tolerant, 0644, tolerant); | ||
1695 | static SYSDEV_INT_ATTR(monarch_timeout, 0644, monarch_timeout); | ||
1696 | |||
1697 | static struct sysdev_ext_attribute attr_check_interval = { | ||
1698 | _SYSDEV_ATTR(check_interval, 0644, sysdev_show_int, | ||
1699 | store_int_with_restart), | ||
1700 | &check_interval | ||
1701 | }; | ||
1702 | |||
1703 | static struct sysdev_attribute *mce_attrs[] = { | ||
1704 | &attr_tolerant.attr, &attr_check_interval.attr, &attr_trigger, | ||
1705 | &attr_monarch_timeout.attr, | ||
1706 | NULL | ||
1707 | }; | ||
1708 | |||
1709 | static cpumask_var_t mce_dev_initialized; | ||
1710 | |||
1711 | /* Per cpu sysdev init. All of the cpus still share the same ctrl bank: */ | ||
1712 | static __cpuinit int mce_create_device(unsigned int cpu) | ||
1713 | { | ||
1714 | int err; | ||
1715 | int i; | ||
1716 | |||
1717 | if (!mce_available(&boot_cpu_data)) | ||
1718 | return -EIO; | ||
1719 | |||
1720 | memset(&per_cpu(mce_dev, cpu).kobj, 0, sizeof(struct kobject)); | ||
1721 | per_cpu(mce_dev, cpu).id = cpu; | ||
1722 | per_cpu(mce_dev, cpu).cls = &mce_sysclass; | ||
1723 | |||
1724 | err = sysdev_register(&per_cpu(mce_dev, cpu)); | ||
1725 | if (err) | ||
1726 | return err; | ||
1727 | |||
1728 | for (i = 0; mce_attrs[i]; i++) { | ||
1729 | err = sysdev_create_file(&per_cpu(mce_dev, cpu), mce_attrs[i]); | ||
1730 | if (err) | ||
1731 | goto error; | ||
1732 | } | ||
1733 | for (i = 0; i < banks; i++) { | ||
1734 | err = sysdev_create_file(&per_cpu(mce_dev, cpu), | ||
1735 | &bank_attrs[i]); | ||
1736 | if (err) | ||
1737 | goto error2; | ||
1738 | } | ||
1739 | cpumask_set_cpu(cpu, mce_dev_initialized); | ||
1740 | |||
1741 | return 0; | ||
1742 | error2: | ||
1743 | while (--i >= 0) | ||
1744 | sysdev_remove_file(&per_cpu(mce_dev, cpu), &bank_attrs[i]); | ||
1745 | error: | ||
1746 | while (--i >= 0) | ||
1747 | sysdev_remove_file(&per_cpu(mce_dev, cpu), mce_attrs[i]); | ||
1748 | |||
1749 | sysdev_unregister(&per_cpu(mce_dev, cpu)); | ||
1750 | |||
1751 | return err; | ||
1752 | } | ||
1753 | |||
1754 | static __cpuinit void mce_remove_device(unsigned int cpu) | ||
1755 | { | ||
1756 | int i; | ||
1757 | |||
1758 | if (!cpumask_test_cpu(cpu, mce_dev_initialized)) | ||
1759 | return; | ||
1760 | |||
1761 | for (i = 0; mce_attrs[i]; i++) | ||
1762 | sysdev_remove_file(&per_cpu(mce_dev, cpu), mce_attrs[i]); | ||
1763 | |||
1764 | for (i = 0; i < banks; i++) | ||
1765 | sysdev_remove_file(&per_cpu(mce_dev, cpu), &bank_attrs[i]); | ||
1766 | |||
1767 | sysdev_unregister(&per_cpu(mce_dev, cpu)); | ||
1768 | cpumask_clear_cpu(cpu, mce_dev_initialized); | ||
1769 | } | ||
1770 | |||
1771 | /* Make sure there are no machine checks on offlined CPUs. */ | ||
1772 | static void mce_disable_cpu(void *h) | ||
1773 | { | ||
1774 | unsigned long action = *(unsigned long *)h; | ||
1775 | int i; | ||
1776 | |||
1777 | if (!mce_available(¤t_cpu_data)) | ||
1778 | return; | ||
1779 | if (!(action & CPU_TASKS_FROZEN)) | ||
1780 | cmci_clear(); | ||
1781 | for (i = 0; i < banks; i++) { | ||
1782 | if (!skip_bank_init(i)) | ||
1783 | wrmsrl(MSR_IA32_MC0_CTL + i*4, 0); | ||
1784 | } | ||
1785 | } | ||
1786 | |||
1787 | static void mce_reenable_cpu(void *h) | ||
1788 | { | ||
1789 | unsigned long action = *(unsigned long *)h; | ||
1790 | int i; | ||
1791 | |||
1792 | if (!mce_available(¤t_cpu_data)) | ||
1793 | return; | ||
1794 | |||
1795 | if (!(action & CPU_TASKS_FROZEN)) | ||
1796 | cmci_reenable(); | ||
1797 | for (i = 0; i < banks; i++) { | ||
1798 | if (!skip_bank_init(i)) | ||
1799 | wrmsrl(MSR_IA32_MC0_CTL + i*4, bank[i]); | ||
1800 | } | ||
1801 | } | ||
1802 | |||
1803 | /* Get notified when a cpu comes on/off. Be hotplug friendly. */ | ||
1804 | static int __cpuinit | ||
1805 | mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) | ||
1806 | { | ||
1807 | unsigned int cpu = (unsigned long)hcpu; | ||
1808 | struct timer_list *t = &per_cpu(mce_timer, cpu); | ||
1809 | |||
1810 | switch (action) { | ||
1811 | case CPU_ONLINE: | ||
1812 | case CPU_ONLINE_FROZEN: | ||
1813 | mce_create_device(cpu); | ||
1814 | if (threshold_cpu_callback) | ||
1815 | threshold_cpu_callback(action, cpu); | ||
1816 | break; | ||
1817 | case CPU_DEAD: | ||
1818 | case CPU_DEAD_FROZEN: | ||
1819 | if (threshold_cpu_callback) | ||
1820 | threshold_cpu_callback(action, cpu); | ||
1821 | mce_remove_device(cpu); | ||
1822 | break; | ||
1823 | case CPU_DOWN_PREPARE: | ||
1824 | case CPU_DOWN_PREPARE_FROZEN: | ||
1825 | del_timer_sync(t); | ||
1826 | smp_call_function_single(cpu, mce_disable_cpu, &action, 1); | ||
1827 | break; | ||
1828 | case CPU_DOWN_FAILED: | ||
1829 | case CPU_DOWN_FAILED_FROZEN: | ||
1830 | t->expires = round_jiffies(jiffies + | ||
1831 | __get_cpu_var(next_interval)); | ||
1832 | add_timer_on(t, cpu); | ||
1833 | smp_call_function_single(cpu, mce_reenable_cpu, &action, 1); | ||
1834 | break; | ||
1835 | case CPU_POST_DEAD: | ||
1836 | /* intentionally ignoring frozen here */ | ||
1837 | cmci_rediscover(cpu); | ||
1838 | break; | ||
1839 | } | ||
1840 | return NOTIFY_OK; | ||
1841 | } | ||
1842 | |||
1843 | static struct notifier_block mce_cpu_notifier __cpuinitdata = { | ||
1844 | .notifier_call = mce_cpu_callback, | ||
1845 | }; | ||
1846 | |||
1847 | static __init int mce_init_banks(void) | ||
1848 | { | ||
1849 | int i; | ||
1850 | |||
1851 | bank_attrs = kzalloc(sizeof(struct sysdev_attribute) * banks, | ||
1852 | GFP_KERNEL); | ||
1853 | if (!bank_attrs) | ||
1854 | return -ENOMEM; | ||
1855 | |||
1856 | for (i = 0; i < banks; i++) { | ||
1857 | struct sysdev_attribute *a = &bank_attrs[i]; | ||
1858 | |||
1859 | a->attr.name = kasprintf(GFP_KERNEL, "bank%d", i); | ||
1860 | if (!a->attr.name) | ||
1861 | goto nomem; | ||
1862 | |||
1863 | a->attr.mode = 0644; | ||
1864 | a->show = show_bank; | ||
1865 | a->store = set_bank; | ||
1866 | } | ||
1867 | return 0; | ||
1868 | |||
1869 | nomem: | ||
1870 | while (--i >= 0) | ||
1871 | kfree(bank_attrs[i].attr.name); | ||
1872 | kfree(bank_attrs); | ||
1873 | bank_attrs = NULL; | ||
1874 | |||
1875 | return -ENOMEM; | ||
1876 | } | ||
1877 | |||
1878 | static __init int mce_init_device(void) | ||
1879 | { | ||
1880 | int err; | ||
1881 | int i = 0; | ||
1882 | |||
1883 | if (!mce_available(&boot_cpu_data)) | ||
1884 | return -EIO; | ||
1885 | |||
1886 | alloc_cpumask_var(&mce_dev_initialized, GFP_KERNEL); | ||
1887 | |||
1888 | err = mce_init_banks(); | ||
1889 | if (err) | ||
1890 | return err; | ||
1891 | |||
1892 | err = sysdev_class_register(&mce_sysclass); | ||
1893 | if (err) | ||
1894 | return err; | ||
1895 | |||
1896 | for_each_online_cpu(i) { | ||
1897 | err = mce_create_device(i); | ||
1898 | if (err) | ||
1899 | return err; | ||
1900 | } | ||
1901 | |||
1902 | register_hotcpu_notifier(&mce_cpu_notifier); | ||
1903 | misc_register(&mce_log_device); | ||
1904 | |||
1905 | return err; | ||
1906 | } | ||
1907 | |||
1908 | device_initcall(mce_init_device); | ||
1909 | |||
1910 | #else /* CONFIG_X86_OLD_MCE: */ | ||
1911 | |||
1912 | int nr_mce_banks; | ||
1913 | EXPORT_SYMBOL_GPL(nr_mce_banks); /* non-fatal.o */ | ||
1914 | |||
1915 | /* This has to be run for each processor */ | ||
1916 | void mcheck_init(struct cpuinfo_x86 *c) | ||
1917 | { | ||
1918 | if (mce_disabled == 1) | ||
1919 | return; | ||
1920 | |||
1921 | switch (c->x86_vendor) { | ||
1922 | case X86_VENDOR_AMD: | ||
1923 | amd_mcheck_init(c); | ||
1924 | break; | ||
1925 | |||
1926 | case X86_VENDOR_INTEL: | ||
1927 | if (c->x86 == 5) | ||
1928 | intel_p5_mcheck_init(c); | ||
1929 | if (c->x86 == 6) | ||
1930 | intel_p6_mcheck_init(c); | ||
1931 | if (c->x86 == 15) | ||
1932 | intel_p4_mcheck_init(c); | ||
1933 | break; | ||
1934 | |||
1935 | case X86_VENDOR_CENTAUR: | ||
1936 | if (c->x86 == 5) | ||
1937 | winchip_mcheck_init(c); | ||
1938 | break; | ||
1939 | |||
1940 | default: | ||
1941 | break; | ||
1942 | } | ||
1943 | printk(KERN_INFO "mce: CPU supports %d MCE banks\n", nr_mce_banks); | ||
1944 | } | ||
1945 | |||
1946 | static int __init mcheck_enable(char *str) | ||
1947 | { | ||
1948 | mce_disabled = -1; | ||
1949 | return 1; | ||
1950 | } | ||
1951 | |||
1952 | __setup("mce", mcheck_enable); | ||
1953 | |||
1954 | #endif /* CONFIG_X86_OLD_MCE */ | ||
1955 | |||
1956 | /* | ||
1957 | * Old style boot options parsing. Only for compatibility. | ||
1958 | */ | ||
1959 | static int __init mcheck_disable(char *str) | ||
1960 | { | ||
1961 | mce_disabled = 1; | ||
1962 | return 1; | ||
1963 | } | ||
1964 | __setup("nomce", mcheck_disable); | ||
diff --git a/arch/x86/kernel/cpu/mcheck/mce.h b/arch/x86/kernel/cpu/mcheck/mce.h index ae9f628838f1..84a552b458c8 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.h +++ b/arch/x86/kernel/cpu/mcheck/mce.h | |||
@@ -1,14 +1,38 @@ | |||
1 | #include <linux/init.h> | 1 | #include <linux/init.h> |
2 | #include <asm/mce.h> | 2 | #include <asm/mce.h> |
3 | 3 | ||
4 | #ifdef CONFIG_X86_OLD_MCE | ||
4 | void amd_mcheck_init(struct cpuinfo_x86 *c); | 5 | void amd_mcheck_init(struct cpuinfo_x86 *c); |
5 | void intel_p4_mcheck_init(struct cpuinfo_x86 *c); | 6 | void intel_p4_mcheck_init(struct cpuinfo_x86 *c); |
6 | void intel_p5_mcheck_init(struct cpuinfo_x86 *c); | ||
7 | void intel_p6_mcheck_init(struct cpuinfo_x86 *c); | 7 | void intel_p6_mcheck_init(struct cpuinfo_x86 *c); |
8 | #endif | ||
9 | |||
10 | #ifdef CONFIG_X86_ANCIENT_MCE | ||
11 | void intel_p5_mcheck_init(struct cpuinfo_x86 *c); | ||
8 | void winchip_mcheck_init(struct cpuinfo_x86 *c); | 12 | void winchip_mcheck_init(struct cpuinfo_x86 *c); |
13 | extern int mce_p5_enable; | ||
14 | static inline int mce_p5_enabled(void) { return mce_p5_enable; } | ||
15 | static inline void enable_p5_mce(void) { mce_p5_enable = 1; } | ||
16 | #else | ||
17 | static inline void intel_p5_mcheck_init(struct cpuinfo_x86 *c) {} | ||
18 | static inline void winchip_mcheck_init(struct cpuinfo_x86 *c) {} | ||
19 | static inline int mce_p5_enabled(void) { return 0; } | ||
20 | static inline void enable_p5_mce(void) { } | ||
21 | #endif | ||
9 | 22 | ||
10 | /* Call the installed machine check handler for this CPU setup. */ | 23 | /* Call the installed machine check handler for this CPU setup. */ |
11 | extern void (*machine_check_vector)(struct pt_regs *, long error_code); | 24 | extern void (*machine_check_vector)(struct pt_regs *, long error_code); |
12 | 25 | ||
26 | #ifdef CONFIG_X86_OLD_MCE | ||
27 | |||
13 | extern int nr_mce_banks; | 28 | extern int nr_mce_banks; |
14 | 29 | ||
30 | void intel_set_thermal_handler(void); | ||
31 | |||
32 | #else | ||
33 | |||
34 | static inline void intel_set_thermal_handler(void) { } | ||
35 | |||
36 | #endif | ||
37 | |||
38 | void intel_init_thermal(struct cpuinfo_x86 *c); | ||
diff --git a/arch/x86/kernel/cpu/mcheck/mce_32.c b/arch/x86/kernel/cpu/mcheck/mce_32.c deleted file mode 100644 index 3552119b091d..000000000000 --- a/arch/x86/kernel/cpu/mcheck/mce_32.c +++ /dev/null | |||
@@ -1,76 +0,0 @@ | |||
1 | /* | ||
2 | * mce.c - x86 Machine Check Exception Reporting | ||
3 | * (c) 2002 Alan Cox <alan@lxorguk.ukuu.org.uk>, Dave Jones <davej@redhat.com> | ||
4 | */ | ||
5 | |||
6 | #include <linux/init.h> | ||
7 | #include <linux/types.h> | ||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/module.h> | ||
10 | #include <linux/smp.h> | ||
11 | #include <linux/thread_info.h> | ||
12 | |||
13 | #include <asm/processor.h> | ||
14 | #include <asm/system.h> | ||
15 | #include <asm/mce.h> | ||
16 | |||
17 | #include "mce.h" | ||
18 | |||
19 | int mce_disabled; | ||
20 | int nr_mce_banks; | ||
21 | |||
22 | EXPORT_SYMBOL_GPL(nr_mce_banks); /* non-fatal.o */ | ||
23 | |||
24 | /* Handle unconfigured int18 (should never happen) */ | ||
25 | static void unexpected_machine_check(struct pt_regs *regs, long error_code) | ||
26 | { | ||
27 | printk(KERN_ERR "CPU#%d: Unexpected int18 (Machine Check).\n", smp_processor_id()); | ||
28 | } | ||
29 | |||
30 | /* Call the installed machine check handler for this CPU setup. */ | ||
31 | void (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_machine_check; | ||
32 | |||
33 | /* This has to be run for each processor */ | ||
34 | void mcheck_init(struct cpuinfo_x86 *c) | ||
35 | { | ||
36 | if (mce_disabled == 1) | ||
37 | return; | ||
38 | |||
39 | switch (c->x86_vendor) { | ||
40 | case X86_VENDOR_AMD: | ||
41 | amd_mcheck_init(c); | ||
42 | break; | ||
43 | |||
44 | case X86_VENDOR_INTEL: | ||
45 | if (c->x86 == 5) | ||
46 | intel_p5_mcheck_init(c); | ||
47 | if (c->x86 == 6) | ||
48 | intel_p6_mcheck_init(c); | ||
49 | if (c->x86 == 15) | ||
50 | intel_p4_mcheck_init(c); | ||
51 | break; | ||
52 | |||
53 | case X86_VENDOR_CENTAUR: | ||
54 | if (c->x86 == 5) | ||
55 | winchip_mcheck_init(c); | ||
56 | break; | ||
57 | |||
58 | default: | ||
59 | break; | ||
60 | } | ||
61 | } | ||
62 | |||
63 | static int __init mcheck_disable(char *str) | ||
64 | { | ||
65 | mce_disabled = 1; | ||
66 | return 1; | ||
67 | } | ||
68 | |||
69 | static int __init mcheck_enable(char *str) | ||
70 | { | ||
71 | mce_disabled = -1; | ||
72 | return 1; | ||
73 | } | ||
74 | |||
75 | __setup("nomce", mcheck_disable); | ||
76 | __setup("mce", mcheck_enable); | ||
diff --git a/arch/x86/kernel/cpu/mcheck/mce_64.c b/arch/x86/kernel/cpu/mcheck/mce_64.c deleted file mode 100644 index 289cc4815028..000000000000 --- a/arch/x86/kernel/cpu/mcheck/mce_64.c +++ /dev/null | |||
@@ -1,1188 +0,0 @@ | |||
1 | /* | ||
2 | * Machine check handler. | ||
3 | * K8 parts Copyright 2002,2003 Andi Kleen, SuSE Labs. | ||
4 | * Rest from unknown author(s). | ||
5 | * 2004 Andi Kleen. Rewrote most of it. | ||
6 | * Copyright 2008 Intel Corporation | ||
7 | * Author: Andi Kleen | ||
8 | */ | ||
9 | |||
10 | #include <linux/init.h> | ||
11 | #include <linux/types.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/sched.h> | ||
14 | #include <linux/smp_lock.h> | ||
15 | #include <linux/string.h> | ||
16 | #include <linux/rcupdate.h> | ||
17 | #include <linux/kallsyms.h> | ||
18 | #include <linux/sysdev.h> | ||
19 | #include <linux/miscdevice.h> | ||
20 | #include <linux/fs.h> | ||
21 | #include <linux/capability.h> | ||
22 | #include <linux/cpu.h> | ||
23 | #include <linux/percpu.h> | ||
24 | #include <linux/poll.h> | ||
25 | #include <linux/thread_info.h> | ||
26 | #include <linux/ctype.h> | ||
27 | #include <linux/kmod.h> | ||
28 | #include <linux/kdebug.h> | ||
29 | #include <linux/kobject.h> | ||
30 | #include <linux/sysfs.h> | ||
31 | #include <linux/ratelimit.h> | ||
32 | #include <asm/processor.h> | ||
33 | #include <asm/msr.h> | ||
34 | #include <asm/mce.h> | ||
35 | #include <asm/uaccess.h> | ||
36 | #include <asm/smp.h> | ||
37 | #include <asm/idle.h> | ||
38 | |||
39 | #define MISC_MCELOG_MINOR 227 | ||
40 | |||
41 | atomic_t mce_entry; | ||
42 | |||
43 | static int mce_dont_init; | ||
44 | |||
45 | /* | ||
46 | * Tolerant levels: | ||
47 | * 0: always panic on uncorrected errors, log corrected errors | ||
48 | * 1: panic or SIGBUS on uncorrected errors, log corrected errors | ||
49 | * 2: SIGBUS or log uncorrected errors (if possible), log corrected errors | ||
50 | * 3: never panic or SIGBUS, log all errors (for testing only) | ||
51 | */ | ||
52 | static int tolerant = 1; | ||
53 | static int banks; | ||
54 | static u64 *bank; | ||
55 | static unsigned long notify_user; | ||
56 | static int rip_msr; | ||
57 | static int mce_bootlog = -1; | ||
58 | static atomic_t mce_events; | ||
59 | |||
60 | static char trigger[128]; | ||
61 | static char *trigger_argv[2] = { trigger, NULL }; | ||
62 | |||
63 | static DECLARE_WAIT_QUEUE_HEAD(mce_wait); | ||
64 | |||
65 | /* MCA banks polled by the period polling timer for corrected events */ | ||
66 | DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = { | ||
67 | [0 ... BITS_TO_LONGS(MAX_NR_BANKS)-1] = ~0UL | ||
68 | }; | ||
69 | |||
70 | /* Do initial initialization of a struct mce */ | ||
71 | void mce_setup(struct mce *m) | ||
72 | { | ||
73 | memset(m, 0, sizeof(struct mce)); | ||
74 | m->cpu = smp_processor_id(); | ||
75 | rdtscll(m->tsc); | ||
76 | } | ||
77 | |||
78 | /* | ||
79 | * Lockless MCE logging infrastructure. | ||
80 | * This avoids deadlocks on printk locks without having to break locks. Also | ||
81 | * separate MCEs from kernel messages to avoid bogus bug reports. | ||
82 | */ | ||
83 | |||
84 | static struct mce_log mcelog = { | ||
85 | MCE_LOG_SIGNATURE, | ||
86 | MCE_LOG_LEN, | ||
87 | }; | ||
88 | |||
89 | void mce_log(struct mce *mce) | ||
90 | { | ||
91 | unsigned next, entry; | ||
92 | atomic_inc(&mce_events); | ||
93 | mce->finished = 0; | ||
94 | wmb(); | ||
95 | for (;;) { | ||
96 | entry = rcu_dereference(mcelog.next); | ||
97 | for (;;) { | ||
98 | /* When the buffer fills up discard new entries. Assume | ||
99 | that the earlier errors are the more interesting. */ | ||
100 | if (entry >= MCE_LOG_LEN) { | ||
101 | set_bit(MCE_OVERFLOW, (unsigned long *)&mcelog.flags); | ||
102 | return; | ||
103 | } | ||
104 | /* Old left over entry. Skip. */ | ||
105 | if (mcelog.entry[entry].finished) { | ||
106 | entry++; | ||
107 | continue; | ||
108 | } | ||
109 | break; | ||
110 | } | ||
111 | smp_rmb(); | ||
112 | next = entry + 1; | ||
113 | if (cmpxchg(&mcelog.next, entry, next) == entry) | ||
114 | break; | ||
115 | } | ||
116 | memcpy(mcelog.entry + entry, mce, sizeof(struct mce)); | ||
117 | wmb(); | ||
118 | mcelog.entry[entry].finished = 1; | ||
119 | wmb(); | ||
120 | |||
121 | set_bit(0, ¬ify_user); | ||
122 | } | ||
123 | |||
124 | static void print_mce(struct mce *m) | ||
125 | { | ||
126 | printk(KERN_EMERG "\n" | ||
127 | KERN_EMERG "HARDWARE ERROR\n" | ||
128 | KERN_EMERG | ||
129 | "CPU %d: Machine Check Exception: %16Lx Bank %d: %016Lx\n", | ||
130 | m->cpu, m->mcgstatus, m->bank, m->status); | ||
131 | if (m->ip) { | ||
132 | printk(KERN_EMERG "RIP%s %02x:<%016Lx> ", | ||
133 | !(m->mcgstatus & MCG_STATUS_EIPV) ? " !INEXACT!" : "", | ||
134 | m->cs, m->ip); | ||
135 | if (m->cs == __KERNEL_CS) | ||
136 | print_symbol("{%s}", m->ip); | ||
137 | printk("\n"); | ||
138 | } | ||
139 | printk(KERN_EMERG "TSC %llx ", m->tsc); | ||
140 | if (m->addr) | ||
141 | printk("ADDR %llx ", m->addr); | ||
142 | if (m->misc) | ||
143 | printk("MISC %llx ", m->misc); | ||
144 | printk("\n"); | ||
145 | printk(KERN_EMERG "This is not a software problem!\n"); | ||
146 | printk(KERN_EMERG "Run through mcelog --ascii to decode " | ||
147 | "and contact your hardware vendor\n"); | ||
148 | } | ||
149 | |||
150 | static void mce_panic(char *msg, struct mce *backup, unsigned long start) | ||
151 | { | ||
152 | int i; | ||
153 | |||
154 | oops_begin(); | ||
155 | for (i = 0; i < MCE_LOG_LEN; i++) { | ||
156 | unsigned long tsc = mcelog.entry[i].tsc; | ||
157 | |||
158 | if (time_before(tsc, start)) | ||
159 | continue; | ||
160 | print_mce(&mcelog.entry[i]); | ||
161 | if (backup && mcelog.entry[i].tsc == backup->tsc) | ||
162 | backup = NULL; | ||
163 | } | ||
164 | if (backup) | ||
165 | print_mce(backup); | ||
166 | panic(msg); | ||
167 | } | ||
168 | |||
169 | int mce_available(struct cpuinfo_x86 *c) | ||
170 | { | ||
171 | if (mce_dont_init) | ||
172 | return 0; | ||
173 | return cpu_has(c, X86_FEATURE_MCE) && cpu_has(c, X86_FEATURE_MCA); | ||
174 | } | ||
175 | |||
176 | static inline void mce_get_rip(struct mce *m, struct pt_regs *regs) | ||
177 | { | ||
178 | if (regs && (m->mcgstatus & MCG_STATUS_RIPV)) { | ||
179 | m->ip = regs->ip; | ||
180 | m->cs = regs->cs; | ||
181 | } else { | ||
182 | m->ip = 0; | ||
183 | m->cs = 0; | ||
184 | } | ||
185 | if (rip_msr) { | ||
186 | /* Assume the RIP in the MSR is exact. Is this true? */ | ||
187 | m->mcgstatus |= MCG_STATUS_EIPV; | ||
188 | rdmsrl(rip_msr, m->ip); | ||
189 | m->cs = 0; | ||
190 | } | ||
191 | } | ||
192 | |||
193 | /* | ||
194 | * Poll for corrected events or events that happened before reset. | ||
195 | * Those are just logged through /dev/mcelog. | ||
196 | * | ||
197 | * This is executed in standard interrupt context. | ||
198 | */ | ||
199 | void machine_check_poll(enum mcp_flags flags, mce_banks_t *b) | ||
200 | { | ||
201 | struct mce m; | ||
202 | int i; | ||
203 | |||
204 | mce_setup(&m); | ||
205 | |||
206 | rdmsrl(MSR_IA32_MCG_STATUS, m.mcgstatus); | ||
207 | for (i = 0; i < banks; i++) { | ||
208 | if (!bank[i] || !test_bit(i, *b)) | ||
209 | continue; | ||
210 | |||
211 | m.misc = 0; | ||
212 | m.addr = 0; | ||
213 | m.bank = i; | ||
214 | m.tsc = 0; | ||
215 | |||
216 | barrier(); | ||
217 | rdmsrl(MSR_IA32_MC0_STATUS + i*4, m.status); | ||
218 | if (!(m.status & MCI_STATUS_VAL)) | ||
219 | continue; | ||
220 | |||
221 | /* | ||
222 | * Uncorrected events are handled by the exception handler | ||
223 | * when it is enabled. But when the exception is disabled log | ||
224 | * everything. | ||
225 | * | ||
226 | * TBD do the same check for MCI_STATUS_EN here? | ||
227 | */ | ||
228 | if ((m.status & MCI_STATUS_UC) && !(flags & MCP_UC)) | ||
229 | continue; | ||
230 | |||
231 | if (m.status & MCI_STATUS_MISCV) | ||
232 | rdmsrl(MSR_IA32_MC0_MISC + i*4, m.misc); | ||
233 | if (m.status & MCI_STATUS_ADDRV) | ||
234 | rdmsrl(MSR_IA32_MC0_ADDR + i*4, m.addr); | ||
235 | |||
236 | if (!(flags & MCP_TIMESTAMP)) | ||
237 | m.tsc = 0; | ||
238 | /* | ||
239 | * Don't get the IP here because it's unlikely to | ||
240 | * have anything to do with the actual error location. | ||
241 | */ | ||
242 | if (!(flags & MCP_DONTLOG)) { | ||
243 | mce_log(&m); | ||
244 | add_taint(TAINT_MACHINE_CHECK); | ||
245 | } | ||
246 | |||
247 | /* | ||
248 | * Clear state for this bank. | ||
249 | */ | ||
250 | wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0); | ||
251 | } | ||
252 | |||
253 | /* | ||
254 | * Don't clear MCG_STATUS here because it's only defined for | ||
255 | * exceptions. | ||
256 | */ | ||
257 | } | ||
258 | |||
259 | /* | ||
260 | * The actual machine check handler. This only handles real | ||
261 | * exceptions when something got corrupted coming in through int 18. | ||
262 | * | ||
263 | * This is executed in NMI context not subject to normal locking rules. This | ||
264 | * implies that most kernel services cannot be safely used. Don't even | ||
265 | * think about putting a printk in there! | ||
266 | */ | ||
267 | void do_machine_check(struct pt_regs * regs, long error_code) | ||
268 | { | ||
269 | struct mce m, panicm; | ||
270 | u64 mcestart = 0; | ||
271 | int i; | ||
272 | int panicm_found = 0; | ||
273 | /* | ||
274 | * If no_way_out gets set, there is no safe way to recover from this | ||
275 | * MCE. If tolerant is cranked up, we'll try anyway. | ||
276 | */ | ||
277 | int no_way_out = 0; | ||
278 | /* | ||
279 | * If kill_it gets set, there might be a way to recover from this | ||
280 | * error. | ||
281 | */ | ||
282 | int kill_it = 0; | ||
283 | DECLARE_BITMAP(toclear, MAX_NR_BANKS); | ||
284 | |||
285 | atomic_inc(&mce_entry); | ||
286 | |||
287 | if (notify_die(DIE_NMI, "machine check", regs, error_code, | ||
288 | 18, SIGKILL) == NOTIFY_STOP) | ||
289 | goto out2; | ||
290 | if (!banks) | ||
291 | goto out2; | ||
292 | |||
293 | mce_setup(&m); | ||
294 | |||
295 | rdmsrl(MSR_IA32_MCG_STATUS, m.mcgstatus); | ||
296 | /* if the restart IP is not valid, we're done for */ | ||
297 | if (!(m.mcgstatus & MCG_STATUS_RIPV)) | ||
298 | no_way_out = 1; | ||
299 | |||
300 | rdtscll(mcestart); | ||
301 | barrier(); | ||
302 | |||
303 | for (i = 0; i < banks; i++) { | ||
304 | __clear_bit(i, toclear); | ||
305 | if (!bank[i]) | ||
306 | continue; | ||
307 | |||
308 | m.misc = 0; | ||
309 | m.addr = 0; | ||
310 | m.bank = i; | ||
311 | |||
312 | rdmsrl(MSR_IA32_MC0_STATUS + i*4, m.status); | ||
313 | if ((m.status & MCI_STATUS_VAL) == 0) | ||
314 | continue; | ||
315 | |||
316 | /* | ||
317 | * Non uncorrected errors are handled by machine_check_poll | ||
318 | * Leave them alone. | ||
319 | */ | ||
320 | if ((m.status & MCI_STATUS_UC) == 0) | ||
321 | continue; | ||
322 | |||
323 | /* | ||
324 | * Set taint even when machine check was not enabled. | ||
325 | */ | ||
326 | add_taint(TAINT_MACHINE_CHECK); | ||
327 | |||
328 | __set_bit(i, toclear); | ||
329 | |||
330 | if (m.status & MCI_STATUS_EN) { | ||
331 | /* if PCC was set, there's no way out */ | ||
332 | no_way_out |= !!(m.status & MCI_STATUS_PCC); | ||
333 | /* | ||
334 | * If this error was uncorrectable and there was | ||
335 | * an overflow, we're in trouble. If no overflow, | ||
336 | * we might get away with just killing a task. | ||
337 | */ | ||
338 | if (m.status & MCI_STATUS_UC) { | ||
339 | if (tolerant < 1 || m.status & MCI_STATUS_OVER) | ||
340 | no_way_out = 1; | ||
341 | kill_it = 1; | ||
342 | } | ||
343 | } else { | ||
344 | /* | ||
345 | * Machine check event was not enabled. Clear, but | ||
346 | * ignore. | ||
347 | */ | ||
348 | continue; | ||
349 | } | ||
350 | |||
351 | if (m.status & MCI_STATUS_MISCV) | ||
352 | rdmsrl(MSR_IA32_MC0_MISC + i*4, m.misc); | ||
353 | if (m.status & MCI_STATUS_ADDRV) | ||
354 | rdmsrl(MSR_IA32_MC0_ADDR + i*4, m.addr); | ||
355 | |||
356 | mce_get_rip(&m, regs); | ||
357 | mce_log(&m); | ||
358 | |||
359 | /* Did this bank cause the exception? */ | ||
360 | /* Assume that the bank with uncorrectable errors did it, | ||
361 | and that there is only a single one. */ | ||
362 | if ((m.status & MCI_STATUS_UC) && (m.status & MCI_STATUS_EN)) { | ||
363 | panicm = m; | ||
364 | panicm_found = 1; | ||
365 | } | ||
366 | } | ||
367 | |||
368 | /* If we didn't find an uncorrectable error, pick | ||
369 | the last one (shouldn't happen, just being safe). */ | ||
370 | if (!panicm_found) | ||
371 | panicm = m; | ||
372 | |||
373 | /* | ||
374 | * If we have decided that we just CAN'T continue, and the user | ||
375 | * has not set tolerant to an insane level, give up and die. | ||
376 | */ | ||
377 | if (no_way_out && tolerant < 3) | ||
378 | mce_panic("Machine check", &panicm, mcestart); | ||
379 | |||
380 | /* | ||
381 | * If the error seems to be unrecoverable, something should be | ||
382 | * done. Try to kill as little as possible. If we can kill just | ||
383 | * one task, do that. If the user has set the tolerance very | ||
384 | * high, don't try to do anything at all. | ||
385 | */ | ||
386 | if (kill_it && tolerant < 3) { | ||
387 | int user_space = 0; | ||
388 | |||
389 | /* | ||
390 | * If the EIPV bit is set, it means the saved IP is the | ||
391 | * instruction which caused the MCE. | ||
392 | */ | ||
393 | if (m.mcgstatus & MCG_STATUS_EIPV) | ||
394 | user_space = panicm.ip && (panicm.cs & 3); | ||
395 | |||
396 | /* | ||
397 | * If we know that the error was in user space, send a | ||
398 | * SIGBUS. Otherwise, panic if tolerance is low. | ||
399 | * | ||
400 | * force_sig() takes an awful lot of locks and has a slight | ||
401 | * risk of deadlocking. | ||
402 | */ | ||
403 | if (user_space) { | ||
404 | force_sig(SIGBUS, current); | ||
405 | } else if (panic_on_oops || tolerant < 2) { | ||
406 | mce_panic("Uncorrected machine check", | ||
407 | &panicm, mcestart); | ||
408 | } | ||
409 | } | ||
410 | |||
411 | /* notify userspace ASAP */ | ||
412 | set_thread_flag(TIF_MCE_NOTIFY); | ||
413 | |||
414 | /* the last thing we do is clear state */ | ||
415 | for (i = 0; i < banks; i++) { | ||
416 | if (test_bit(i, toclear)) | ||
417 | wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0); | ||
418 | } | ||
419 | wrmsrl(MSR_IA32_MCG_STATUS, 0); | ||
420 | out2: | ||
421 | atomic_dec(&mce_entry); | ||
422 | } | ||
423 | EXPORT_SYMBOL_GPL(do_machine_check); | ||
424 | |||
425 | #ifdef CONFIG_X86_MCE_INTEL | ||
426 | /*** | ||
427 | * mce_log_therm_throt_event - Logs the thermal throttling event to mcelog | ||
428 | * @cpu: The CPU on which the event occurred. | ||
429 | * @status: Event status information | ||
430 | * | ||
431 | * This function should be called by the thermal interrupt after the | ||
432 | * event has been processed and the decision was made to log the event | ||
433 | * further. | ||
434 | * | ||
435 | * The status parameter will be saved to the 'status' field of 'struct mce' | ||
436 | * and historically has been the register value of the | ||
437 | * MSR_IA32_THERMAL_STATUS (Intel) msr. | ||
438 | */ | ||
439 | void mce_log_therm_throt_event(__u64 status) | ||
440 | { | ||
441 | struct mce m; | ||
442 | |||
443 | mce_setup(&m); | ||
444 | m.bank = MCE_THERMAL_BANK; | ||
445 | m.status = status; | ||
446 | mce_log(&m); | ||
447 | } | ||
448 | #endif /* CONFIG_X86_MCE_INTEL */ | ||
449 | |||
450 | /* | ||
451 | * Periodic polling timer for "silent" machine check errors. If the | ||
452 | * poller finds an MCE, poll 2x faster. When the poller finds no more | ||
453 | * errors, poll 2x slower (up to check_interval seconds). | ||
454 | */ | ||
455 | |||
456 | static int check_interval = 5 * 60; /* 5 minutes */ | ||
457 | static DEFINE_PER_CPU(int, next_interval); /* in jiffies */ | ||
458 | static void mcheck_timer(unsigned long); | ||
459 | static DEFINE_PER_CPU(struct timer_list, mce_timer); | ||
460 | |||
461 | static void mcheck_timer(unsigned long data) | ||
462 | { | ||
463 | struct timer_list *t = &per_cpu(mce_timer, data); | ||
464 | int *n; | ||
465 | |||
466 | WARN_ON(smp_processor_id() != data); | ||
467 | |||
468 | if (mce_available(¤t_cpu_data)) | ||
469 | machine_check_poll(MCP_TIMESTAMP, | ||
470 | &__get_cpu_var(mce_poll_banks)); | ||
471 | |||
472 | /* | ||
473 | * Alert userspace if needed. If we logged an MCE, reduce the | ||
474 | * polling interval, otherwise increase the polling interval. | ||
475 | */ | ||
476 | n = &__get_cpu_var(next_interval); | ||
477 | if (mce_notify_user()) { | ||
478 | *n = max(*n/2, HZ/100); | ||
479 | } else { | ||
480 | *n = min(*n*2, (int)round_jiffies_relative(check_interval*HZ)); | ||
481 | } | ||
482 | |||
483 | t->expires = jiffies + *n; | ||
484 | add_timer(t); | ||
485 | } | ||
486 | |||
487 | static void mce_do_trigger(struct work_struct *work) | ||
488 | { | ||
489 | call_usermodehelper(trigger, trigger_argv, NULL, UMH_NO_WAIT); | ||
490 | } | ||
491 | |||
492 | static DECLARE_WORK(mce_trigger_work, mce_do_trigger); | ||
493 | |||
494 | /* | ||
495 | * Notify the user(s) about new machine check events. | ||
496 | * Can be called from interrupt context, but not from machine check/NMI | ||
497 | * context. | ||
498 | */ | ||
499 | int mce_notify_user(void) | ||
500 | { | ||
501 | /* Not more than two messages every minute */ | ||
502 | static DEFINE_RATELIMIT_STATE(ratelimit, 60*HZ, 2); | ||
503 | |||
504 | clear_thread_flag(TIF_MCE_NOTIFY); | ||
505 | if (test_and_clear_bit(0, ¬ify_user)) { | ||
506 | wake_up_interruptible(&mce_wait); | ||
507 | |||
508 | /* | ||
509 | * There is no risk of missing notifications because | ||
510 | * work_pending is always cleared before the function is | ||
511 | * executed. | ||
512 | */ | ||
513 | if (trigger[0] && !work_pending(&mce_trigger_work)) | ||
514 | schedule_work(&mce_trigger_work); | ||
515 | |||
516 | if (__ratelimit(&ratelimit)) | ||
517 | printk(KERN_INFO "Machine check events logged\n"); | ||
518 | |||
519 | return 1; | ||
520 | } | ||
521 | return 0; | ||
522 | } | ||
523 | |||
524 | /* see if the idle task needs to notify userspace */ | ||
525 | static int | ||
526 | mce_idle_callback(struct notifier_block *nfb, unsigned long action, void *junk) | ||
527 | { | ||
528 | /* IDLE_END should be safe - interrupts are back on */ | ||
529 | if (action == IDLE_END && test_thread_flag(TIF_MCE_NOTIFY)) | ||
530 | mce_notify_user(); | ||
531 | |||
532 | return NOTIFY_OK; | ||
533 | } | ||
534 | |||
535 | static struct notifier_block mce_idle_notifier = { | ||
536 | .notifier_call = mce_idle_callback, | ||
537 | }; | ||
538 | |||
539 | static __init int periodic_mcheck_init(void) | ||
540 | { | ||
541 | idle_notifier_register(&mce_idle_notifier); | ||
542 | return 0; | ||
543 | } | ||
544 | __initcall(periodic_mcheck_init); | ||
545 | |||
546 | /* | ||
547 | * Initialize Machine Checks for a CPU. | ||
548 | */ | ||
549 | static int mce_cap_init(void) | ||
550 | { | ||
551 | u64 cap; | ||
552 | unsigned b; | ||
553 | |||
554 | rdmsrl(MSR_IA32_MCG_CAP, cap); | ||
555 | b = cap & 0xff; | ||
556 | if (b > MAX_NR_BANKS) { | ||
557 | printk(KERN_WARNING | ||
558 | "MCE: Using only %u machine check banks out of %u\n", | ||
559 | MAX_NR_BANKS, b); | ||
560 | b = MAX_NR_BANKS; | ||
561 | } | ||
562 | |||
563 | /* Don't support asymmetric configurations today */ | ||
564 | WARN_ON(banks != 0 && b != banks); | ||
565 | banks = b; | ||
566 | if (!bank) { | ||
567 | bank = kmalloc(banks * sizeof(u64), GFP_KERNEL); | ||
568 | if (!bank) | ||
569 | return -ENOMEM; | ||
570 | memset(bank, 0xff, banks * sizeof(u64)); | ||
571 | } | ||
572 | |||
573 | /* Use accurate RIP reporting if available. */ | ||
574 | if ((cap & (1<<9)) && ((cap >> 16) & 0xff) >= 9) | ||
575 | rip_msr = MSR_IA32_MCG_EIP; | ||
576 | |||
577 | return 0; | ||
578 | } | ||
579 | |||
580 | static void mce_init(void *dummy) | ||
581 | { | ||
582 | u64 cap; | ||
583 | int i; | ||
584 | mce_banks_t all_banks; | ||
585 | |||
586 | /* | ||
587 | * Log the machine checks left over from the previous reset. | ||
588 | */ | ||
589 | bitmap_fill(all_banks, MAX_NR_BANKS); | ||
590 | machine_check_poll(MCP_UC|(!mce_bootlog ? MCP_DONTLOG : 0), &all_banks); | ||
591 | |||
592 | set_in_cr4(X86_CR4_MCE); | ||
593 | |||
594 | rdmsrl(MSR_IA32_MCG_CAP, cap); | ||
595 | if (cap & MCG_CTL_P) | ||
596 | wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff); | ||
597 | |||
598 | for (i = 0; i < banks; i++) { | ||
599 | wrmsrl(MSR_IA32_MC0_CTL+4*i, bank[i]); | ||
600 | wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0); | ||
601 | } | ||
602 | } | ||
603 | |||
604 | /* Add per CPU specific workarounds here */ | ||
605 | static void mce_cpu_quirks(struct cpuinfo_x86 *c) | ||
606 | { | ||
607 | /* This should be disabled by the BIOS, but isn't always */ | ||
608 | if (c->x86_vendor == X86_VENDOR_AMD) { | ||
609 | if (c->x86 == 15 && banks > 4) | ||
610 | /* disable GART TBL walk error reporting, which trips off | ||
611 | incorrectly with the IOMMU & 3ware & Cerberus. */ | ||
612 | clear_bit(10, (unsigned long *)&bank[4]); | ||
613 | if(c->x86 <= 17 && mce_bootlog < 0) | ||
614 | /* Lots of broken BIOS around that don't clear them | ||
615 | by default and leave crap in there. Don't log. */ | ||
616 | mce_bootlog = 0; | ||
617 | } | ||
618 | |||
619 | } | ||
620 | |||
621 | static void mce_cpu_features(struct cpuinfo_x86 *c) | ||
622 | { | ||
623 | switch (c->x86_vendor) { | ||
624 | case X86_VENDOR_INTEL: | ||
625 | mce_intel_feature_init(c); | ||
626 | break; | ||
627 | case X86_VENDOR_AMD: | ||
628 | mce_amd_feature_init(c); | ||
629 | break; | ||
630 | default: | ||
631 | break; | ||
632 | } | ||
633 | } | ||
634 | |||
635 | static void mce_init_timer(void) | ||
636 | { | ||
637 | struct timer_list *t = &__get_cpu_var(mce_timer); | ||
638 | int *n = &__get_cpu_var(next_interval); | ||
639 | |||
640 | *n = check_interval * HZ; | ||
641 | if (!*n) | ||
642 | return; | ||
643 | setup_timer(t, mcheck_timer, smp_processor_id()); | ||
644 | t->expires = round_jiffies(jiffies + *n); | ||
645 | add_timer(t); | ||
646 | } | ||
647 | |||
648 | /* | ||
649 | * Called for each booted CPU to set up machine checks. | ||
650 | * Must be called with preempt off. | ||
651 | */ | ||
652 | void __cpuinit mcheck_init(struct cpuinfo_x86 *c) | ||
653 | { | ||
654 | if (!mce_available(c)) | ||
655 | return; | ||
656 | |||
657 | if (mce_cap_init() < 0) { | ||
658 | mce_dont_init = 1; | ||
659 | return; | ||
660 | } | ||
661 | mce_cpu_quirks(c); | ||
662 | |||
663 | mce_init(NULL); | ||
664 | mce_cpu_features(c); | ||
665 | mce_init_timer(); | ||
666 | } | ||
667 | |||
668 | /* | ||
669 | * Character device to read and clear the MCE log. | ||
670 | */ | ||
671 | |||
672 | static DEFINE_SPINLOCK(mce_state_lock); | ||
673 | static int open_count; /* #times opened */ | ||
674 | static int open_exclu; /* already open exclusive? */ | ||
675 | |||
676 | static int mce_open(struct inode *inode, struct file *file) | ||
677 | { | ||
678 | lock_kernel(); | ||
679 | spin_lock(&mce_state_lock); | ||
680 | |||
681 | if (open_exclu || (open_count && (file->f_flags & O_EXCL))) { | ||
682 | spin_unlock(&mce_state_lock); | ||
683 | unlock_kernel(); | ||
684 | return -EBUSY; | ||
685 | } | ||
686 | |||
687 | if (file->f_flags & O_EXCL) | ||
688 | open_exclu = 1; | ||
689 | open_count++; | ||
690 | |||
691 | spin_unlock(&mce_state_lock); | ||
692 | unlock_kernel(); | ||
693 | |||
694 | return nonseekable_open(inode, file); | ||
695 | } | ||
696 | |||
697 | static int mce_release(struct inode *inode, struct file *file) | ||
698 | { | ||
699 | spin_lock(&mce_state_lock); | ||
700 | |||
701 | open_count--; | ||
702 | open_exclu = 0; | ||
703 | |||
704 | spin_unlock(&mce_state_lock); | ||
705 | |||
706 | return 0; | ||
707 | } | ||
708 | |||
709 | static void collect_tscs(void *data) | ||
710 | { | ||
711 | unsigned long *cpu_tsc = (unsigned long *)data; | ||
712 | |||
713 | rdtscll(cpu_tsc[smp_processor_id()]); | ||
714 | } | ||
715 | |||
716 | static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize, | ||
717 | loff_t *off) | ||
718 | { | ||
719 | unsigned long *cpu_tsc; | ||
720 | static DEFINE_MUTEX(mce_read_mutex); | ||
721 | unsigned prev, next; | ||
722 | char __user *buf = ubuf; | ||
723 | int i, err; | ||
724 | |||
725 | cpu_tsc = kmalloc(nr_cpu_ids * sizeof(long), GFP_KERNEL); | ||
726 | if (!cpu_tsc) | ||
727 | return -ENOMEM; | ||
728 | |||
729 | mutex_lock(&mce_read_mutex); | ||
730 | next = rcu_dereference(mcelog.next); | ||
731 | |||
732 | /* Only supports full reads right now */ | ||
733 | if (*off != 0 || usize < MCE_LOG_LEN*sizeof(struct mce)) { | ||
734 | mutex_unlock(&mce_read_mutex); | ||
735 | kfree(cpu_tsc); | ||
736 | return -EINVAL; | ||
737 | } | ||
738 | |||
739 | err = 0; | ||
740 | prev = 0; | ||
741 | do { | ||
742 | for (i = prev; i < next; i++) { | ||
743 | unsigned long start = jiffies; | ||
744 | |||
745 | while (!mcelog.entry[i].finished) { | ||
746 | if (time_after_eq(jiffies, start + 2)) { | ||
747 | memset(mcelog.entry + i, 0, | ||
748 | sizeof(struct mce)); | ||
749 | goto timeout; | ||
750 | } | ||
751 | cpu_relax(); | ||
752 | } | ||
753 | smp_rmb(); | ||
754 | err |= copy_to_user(buf, mcelog.entry + i, | ||
755 | sizeof(struct mce)); | ||
756 | buf += sizeof(struct mce); | ||
757 | timeout: | ||
758 | ; | ||
759 | } | ||
760 | |||
761 | memset(mcelog.entry + prev, 0, | ||
762 | (next - prev) * sizeof(struct mce)); | ||
763 | prev = next; | ||
764 | next = cmpxchg(&mcelog.next, prev, 0); | ||
765 | } while (next != prev); | ||
766 | |||
767 | synchronize_sched(); | ||
768 | |||
769 | /* | ||
770 | * Collect entries that were still getting written before the | ||
771 | * synchronize. | ||
772 | */ | ||
773 | on_each_cpu(collect_tscs, cpu_tsc, 1); | ||
774 | for (i = next; i < MCE_LOG_LEN; i++) { | ||
775 | if (mcelog.entry[i].finished && | ||
776 | mcelog.entry[i].tsc < cpu_tsc[mcelog.entry[i].cpu]) { | ||
777 | err |= copy_to_user(buf, mcelog.entry+i, | ||
778 | sizeof(struct mce)); | ||
779 | smp_rmb(); | ||
780 | buf += sizeof(struct mce); | ||
781 | memset(&mcelog.entry[i], 0, sizeof(struct mce)); | ||
782 | } | ||
783 | } | ||
784 | mutex_unlock(&mce_read_mutex); | ||
785 | kfree(cpu_tsc); | ||
786 | return err ? -EFAULT : buf - ubuf; | ||
787 | } | ||
788 | |||
789 | static unsigned int mce_poll(struct file *file, poll_table *wait) | ||
790 | { | ||
791 | poll_wait(file, &mce_wait, wait); | ||
792 | if (rcu_dereference(mcelog.next)) | ||
793 | return POLLIN | POLLRDNORM; | ||
794 | return 0; | ||
795 | } | ||
796 | |||
797 | static long mce_ioctl(struct file *f, unsigned int cmd, unsigned long arg) | ||
798 | { | ||
799 | int __user *p = (int __user *)arg; | ||
800 | |||
801 | if (!capable(CAP_SYS_ADMIN)) | ||
802 | return -EPERM; | ||
803 | switch (cmd) { | ||
804 | case MCE_GET_RECORD_LEN: | ||
805 | return put_user(sizeof(struct mce), p); | ||
806 | case MCE_GET_LOG_LEN: | ||
807 | return put_user(MCE_LOG_LEN, p); | ||
808 | case MCE_GETCLEAR_FLAGS: { | ||
809 | unsigned flags; | ||
810 | |||
811 | do { | ||
812 | flags = mcelog.flags; | ||
813 | } while (cmpxchg(&mcelog.flags, flags, 0) != flags); | ||
814 | return put_user(flags, p); | ||
815 | } | ||
816 | default: | ||
817 | return -ENOTTY; | ||
818 | } | ||
819 | } | ||
820 | |||
821 | static const struct file_operations mce_chrdev_ops = { | ||
822 | .open = mce_open, | ||
823 | .release = mce_release, | ||
824 | .read = mce_read, | ||
825 | .poll = mce_poll, | ||
826 | .unlocked_ioctl = mce_ioctl, | ||
827 | }; | ||
828 | |||
829 | static struct miscdevice mce_log_device = { | ||
830 | MISC_MCELOG_MINOR, | ||
831 | "mcelog", | ||
832 | &mce_chrdev_ops, | ||
833 | }; | ||
834 | |||
835 | /* | ||
836 | * Old style boot options parsing. Only for compatibility. | ||
837 | */ | ||
838 | static int __init mcheck_disable(char *str) | ||
839 | { | ||
840 | mce_dont_init = 1; | ||
841 | return 1; | ||
842 | } | ||
843 | |||
844 | /* mce=off disables machine check. | ||
845 | mce=TOLERANCELEVEL (number, see above) | ||
846 | mce=bootlog Log MCEs from before booting. Disabled by default on AMD. | ||
847 | mce=nobootlog Don't log MCEs from before booting. */ | ||
848 | static int __init mcheck_enable(char *str) | ||
849 | { | ||
850 | if (!strcmp(str, "off")) | ||
851 | mce_dont_init = 1; | ||
852 | else if (!strcmp(str, "bootlog") || !strcmp(str,"nobootlog")) | ||
853 | mce_bootlog = str[0] == 'b'; | ||
854 | else if (isdigit(str[0])) | ||
855 | get_option(&str, &tolerant); | ||
856 | else | ||
857 | printk("mce= argument %s ignored. Please use /sys", str); | ||
858 | return 1; | ||
859 | } | ||
860 | |||
861 | __setup("nomce", mcheck_disable); | ||
862 | __setup("mce=", mcheck_enable); | ||
863 | |||
864 | /* | ||
865 | * Sysfs support | ||
866 | */ | ||
867 | |||
868 | /* | ||
869 | * Disable machine checks on suspend and shutdown. We can't really handle | ||
870 | * them later. | ||
871 | */ | ||
872 | static int mce_disable(void) | ||
873 | { | ||
874 | int i; | ||
875 | |||
876 | for (i = 0; i < banks; i++) | ||
877 | wrmsrl(MSR_IA32_MC0_CTL + i*4, 0); | ||
878 | return 0; | ||
879 | } | ||
880 | |||
881 | static int mce_suspend(struct sys_device *dev, pm_message_t state) | ||
882 | { | ||
883 | return mce_disable(); | ||
884 | } | ||
885 | |||
886 | static int mce_shutdown(struct sys_device *dev) | ||
887 | { | ||
888 | return mce_disable(); | ||
889 | } | ||
890 | |||
891 | /* On resume clear all MCE state. Don't want to see leftovers from the BIOS. | ||
892 | Only one CPU is active at this time, the others get readded later using | ||
893 | CPU hotplug. */ | ||
894 | static int mce_resume(struct sys_device *dev) | ||
895 | { | ||
896 | mce_init(NULL); | ||
897 | mce_cpu_features(¤t_cpu_data); | ||
898 | return 0; | ||
899 | } | ||
900 | |||
901 | static void mce_cpu_restart(void *data) | ||
902 | { | ||
903 | del_timer_sync(&__get_cpu_var(mce_timer)); | ||
904 | if (mce_available(¤t_cpu_data)) | ||
905 | mce_init(NULL); | ||
906 | mce_init_timer(); | ||
907 | } | ||
908 | |||
909 | /* Reinit MCEs after user configuration changes */ | ||
910 | static void mce_restart(void) | ||
911 | { | ||
912 | on_each_cpu(mce_cpu_restart, NULL, 1); | ||
913 | } | ||
914 | |||
915 | static struct sysdev_class mce_sysclass = { | ||
916 | .suspend = mce_suspend, | ||
917 | .shutdown = mce_shutdown, | ||
918 | .resume = mce_resume, | ||
919 | .name = "machinecheck", | ||
920 | }; | ||
921 | |||
922 | DEFINE_PER_CPU(struct sys_device, device_mce); | ||
923 | void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu) __cpuinitdata; | ||
924 | |||
925 | /* Why are there no generic functions for this? */ | ||
926 | #define ACCESSOR(name, var, start) \ | ||
927 | static ssize_t show_ ## name(struct sys_device *s, \ | ||
928 | struct sysdev_attribute *attr, \ | ||
929 | char *buf) { \ | ||
930 | return sprintf(buf, "%lx\n", (unsigned long)var); \ | ||
931 | } \ | ||
932 | static ssize_t set_ ## name(struct sys_device *s, \ | ||
933 | struct sysdev_attribute *attr, \ | ||
934 | const char *buf, size_t siz) { \ | ||
935 | char *end; \ | ||
936 | unsigned long new = simple_strtoul(buf, &end, 0); \ | ||
937 | if (end == buf) return -EINVAL; \ | ||
938 | var = new; \ | ||
939 | start; \ | ||
940 | return end-buf; \ | ||
941 | } \ | ||
942 | static SYSDEV_ATTR(name, 0644, show_ ## name, set_ ## name); | ||
943 | |||
944 | static struct sysdev_attribute *bank_attrs; | ||
945 | |||
946 | static ssize_t show_bank(struct sys_device *s, struct sysdev_attribute *attr, | ||
947 | char *buf) | ||
948 | { | ||
949 | u64 b = bank[attr - bank_attrs]; | ||
950 | return sprintf(buf, "%llx\n", b); | ||
951 | } | ||
952 | |||
953 | static ssize_t set_bank(struct sys_device *s, struct sysdev_attribute *attr, | ||
954 | const char *buf, size_t siz) | ||
955 | { | ||
956 | char *end; | ||
957 | u64 new = simple_strtoull(buf, &end, 0); | ||
958 | if (end == buf) | ||
959 | return -EINVAL; | ||
960 | bank[attr - bank_attrs] = new; | ||
961 | mce_restart(); | ||
962 | return end-buf; | ||
963 | } | ||
964 | |||
965 | static ssize_t show_trigger(struct sys_device *s, struct sysdev_attribute *attr, | ||
966 | char *buf) | ||
967 | { | ||
968 | strcpy(buf, trigger); | ||
969 | strcat(buf, "\n"); | ||
970 | return strlen(trigger) + 1; | ||
971 | } | ||
972 | |||
973 | static ssize_t set_trigger(struct sys_device *s, struct sysdev_attribute *attr, | ||
974 | const char *buf,size_t siz) | ||
975 | { | ||
976 | char *p; | ||
977 | int len; | ||
978 | strncpy(trigger, buf, sizeof(trigger)); | ||
979 | trigger[sizeof(trigger)-1] = 0; | ||
980 | len = strlen(trigger); | ||
981 | p = strchr(trigger, '\n'); | ||
982 | if (*p) *p = 0; | ||
983 | return len; | ||
984 | } | ||
985 | |||
986 | static SYSDEV_ATTR(trigger, 0644, show_trigger, set_trigger); | ||
987 | static SYSDEV_INT_ATTR(tolerant, 0644, tolerant); | ||
988 | ACCESSOR(check_interval,check_interval,mce_restart()) | ||
989 | static struct sysdev_attribute *mce_attributes[] = { | ||
990 | &attr_tolerant.attr, &attr_check_interval, &attr_trigger, | ||
991 | NULL | ||
992 | }; | ||
993 | |||
994 | static cpumask_var_t mce_device_initialized; | ||
995 | |||
996 | /* Per cpu sysdev init. All of the cpus still share the same ctl bank */ | ||
997 | static __cpuinit int mce_create_device(unsigned int cpu) | ||
998 | { | ||
999 | int err; | ||
1000 | int i; | ||
1001 | |||
1002 | if (!mce_available(&boot_cpu_data)) | ||
1003 | return -EIO; | ||
1004 | |||
1005 | memset(&per_cpu(device_mce, cpu).kobj, 0, sizeof(struct kobject)); | ||
1006 | per_cpu(device_mce,cpu).id = cpu; | ||
1007 | per_cpu(device_mce,cpu).cls = &mce_sysclass; | ||
1008 | |||
1009 | err = sysdev_register(&per_cpu(device_mce,cpu)); | ||
1010 | if (err) | ||
1011 | return err; | ||
1012 | |||
1013 | for (i = 0; mce_attributes[i]; i++) { | ||
1014 | err = sysdev_create_file(&per_cpu(device_mce,cpu), | ||
1015 | mce_attributes[i]); | ||
1016 | if (err) | ||
1017 | goto error; | ||
1018 | } | ||
1019 | for (i = 0; i < banks; i++) { | ||
1020 | err = sysdev_create_file(&per_cpu(device_mce, cpu), | ||
1021 | &bank_attrs[i]); | ||
1022 | if (err) | ||
1023 | goto error2; | ||
1024 | } | ||
1025 | cpumask_set_cpu(cpu, mce_device_initialized); | ||
1026 | |||
1027 | return 0; | ||
1028 | error2: | ||
1029 | while (--i >= 0) { | ||
1030 | sysdev_remove_file(&per_cpu(device_mce, cpu), | ||
1031 | &bank_attrs[i]); | ||
1032 | } | ||
1033 | error: | ||
1034 | while (--i >= 0) { | ||
1035 | sysdev_remove_file(&per_cpu(device_mce,cpu), | ||
1036 | mce_attributes[i]); | ||
1037 | } | ||
1038 | sysdev_unregister(&per_cpu(device_mce,cpu)); | ||
1039 | |||
1040 | return err; | ||
1041 | } | ||
1042 | |||
1043 | static __cpuinit void mce_remove_device(unsigned int cpu) | ||
1044 | { | ||
1045 | int i; | ||
1046 | |||
1047 | if (!cpumask_test_cpu(cpu, mce_device_initialized)) | ||
1048 | return; | ||
1049 | |||
1050 | for (i = 0; mce_attributes[i]; i++) | ||
1051 | sysdev_remove_file(&per_cpu(device_mce,cpu), | ||
1052 | mce_attributes[i]); | ||
1053 | for (i = 0; i < banks; i++) | ||
1054 | sysdev_remove_file(&per_cpu(device_mce, cpu), | ||
1055 | &bank_attrs[i]); | ||
1056 | sysdev_unregister(&per_cpu(device_mce,cpu)); | ||
1057 | cpumask_clear_cpu(cpu, mce_device_initialized); | ||
1058 | } | ||
1059 | |||
1060 | /* Make sure there are no machine checks on offlined CPUs. */ | ||
1061 | static void mce_disable_cpu(void *h) | ||
1062 | { | ||
1063 | int i; | ||
1064 | unsigned long action = *(unsigned long *)h; | ||
1065 | |||
1066 | if (!mce_available(¤t_cpu_data)) | ||
1067 | return; | ||
1068 | if (!(action & CPU_TASKS_FROZEN)) | ||
1069 | cmci_clear(); | ||
1070 | for (i = 0; i < banks; i++) | ||
1071 | wrmsrl(MSR_IA32_MC0_CTL + i*4, 0); | ||
1072 | } | ||
1073 | |||
1074 | static void mce_reenable_cpu(void *h) | ||
1075 | { | ||
1076 | int i; | ||
1077 | unsigned long action = *(unsigned long *)h; | ||
1078 | |||
1079 | if (!mce_available(¤t_cpu_data)) | ||
1080 | return; | ||
1081 | if (!(action & CPU_TASKS_FROZEN)) | ||
1082 | cmci_reenable(); | ||
1083 | for (i = 0; i < banks; i++) | ||
1084 | wrmsrl(MSR_IA32_MC0_CTL + i*4, bank[i]); | ||
1085 | } | ||
1086 | |||
1087 | /* Get notified when a cpu comes on/off. Be hotplug friendly. */ | ||
1088 | static int __cpuinit mce_cpu_callback(struct notifier_block *nfb, | ||
1089 | unsigned long action, void *hcpu) | ||
1090 | { | ||
1091 | unsigned int cpu = (unsigned long)hcpu; | ||
1092 | struct timer_list *t = &per_cpu(mce_timer, cpu); | ||
1093 | |||
1094 | switch (action) { | ||
1095 | case CPU_ONLINE: | ||
1096 | case CPU_ONLINE_FROZEN: | ||
1097 | mce_create_device(cpu); | ||
1098 | if (threshold_cpu_callback) | ||
1099 | threshold_cpu_callback(action, cpu); | ||
1100 | break; | ||
1101 | case CPU_DEAD: | ||
1102 | case CPU_DEAD_FROZEN: | ||
1103 | if (threshold_cpu_callback) | ||
1104 | threshold_cpu_callback(action, cpu); | ||
1105 | mce_remove_device(cpu); | ||
1106 | break; | ||
1107 | case CPU_DOWN_PREPARE: | ||
1108 | case CPU_DOWN_PREPARE_FROZEN: | ||
1109 | del_timer_sync(t); | ||
1110 | smp_call_function_single(cpu, mce_disable_cpu, &action, 1); | ||
1111 | break; | ||
1112 | case CPU_DOWN_FAILED: | ||
1113 | case CPU_DOWN_FAILED_FROZEN: | ||
1114 | t->expires = round_jiffies(jiffies + | ||
1115 | __get_cpu_var(next_interval)); | ||
1116 | add_timer_on(t, cpu); | ||
1117 | smp_call_function_single(cpu, mce_reenable_cpu, &action, 1); | ||
1118 | break; | ||
1119 | case CPU_POST_DEAD: | ||
1120 | /* intentionally ignoring frozen here */ | ||
1121 | cmci_rediscover(cpu); | ||
1122 | break; | ||
1123 | } | ||
1124 | return NOTIFY_OK; | ||
1125 | } | ||
1126 | |||
1127 | static struct notifier_block mce_cpu_notifier __cpuinitdata = { | ||
1128 | .notifier_call = mce_cpu_callback, | ||
1129 | }; | ||
1130 | |||
1131 | static __init int mce_init_banks(void) | ||
1132 | { | ||
1133 | int i; | ||
1134 | |||
1135 | bank_attrs = kzalloc(sizeof(struct sysdev_attribute) * banks, | ||
1136 | GFP_KERNEL); | ||
1137 | if (!bank_attrs) | ||
1138 | return -ENOMEM; | ||
1139 | |||
1140 | for (i = 0; i < banks; i++) { | ||
1141 | struct sysdev_attribute *a = &bank_attrs[i]; | ||
1142 | a->attr.name = kasprintf(GFP_KERNEL, "bank%d", i); | ||
1143 | if (!a->attr.name) | ||
1144 | goto nomem; | ||
1145 | a->attr.mode = 0644; | ||
1146 | a->show = show_bank; | ||
1147 | a->store = set_bank; | ||
1148 | } | ||
1149 | return 0; | ||
1150 | |||
1151 | nomem: | ||
1152 | while (--i >= 0) | ||
1153 | kfree(bank_attrs[i].attr.name); | ||
1154 | kfree(bank_attrs); | ||
1155 | bank_attrs = NULL; | ||
1156 | return -ENOMEM; | ||
1157 | } | ||
1158 | |||
1159 | static __init int mce_init_device(void) | ||
1160 | { | ||
1161 | int err; | ||
1162 | int i = 0; | ||
1163 | |||
1164 | if (!mce_available(&boot_cpu_data)) | ||
1165 | return -EIO; | ||
1166 | |||
1167 | zalloc_cpumask_var(&mce_device_initialized, GFP_KERNEL); | ||
1168 | |||
1169 | err = mce_init_banks(); | ||
1170 | if (err) | ||
1171 | return err; | ||
1172 | |||
1173 | err = sysdev_class_register(&mce_sysclass); | ||
1174 | if (err) | ||
1175 | return err; | ||
1176 | |||
1177 | for_each_online_cpu(i) { | ||
1178 | err = mce_create_device(i); | ||
1179 | if (err) | ||
1180 | return err; | ||
1181 | } | ||
1182 | |||
1183 | register_hotcpu_notifier(&mce_cpu_notifier); | ||
1184 | misc_register(&mce_log_device); | ||
1185 | return err; | ||
1186 | } | ||
1187 | |||
1188 | device_initcall(mce_init_device); | ||
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c index 56dde9c4bc96..ddae21620bda 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c | |||
@@ -13,22 +13,22 @@ | |||
13 | * | 13 | * |
14 | * All MC4_MISCi registers are shared between multi-cores | 14 | * All MC4_MISCi registers are shared between multi-cores |
15 | */ | 15 | */ |
16 | |||
17 | #include <linux/cpu.h> | ||
18 | #include <linux/errno.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
21 | #include <linux/kobject.h> | ||
22 | #include <linux/notifier.h> | 17 | #include <linux/notifier.h> |
23 | #include <linux/sched.h> | 18 | #include <linux/kobject.h> |
24 | #include <linux/smp.h> | 19 | #include <linux/percpu.h> |
25 | #include <linux/sysdev.h> | 20 | #include <linux/sysdev.h> |
21 | #include <linux/errno.h> | ||
22 | #include <linux/sched.h> | ||
26 | #include <linux/sysfs.h> | 23 | #include <linux/sysfs.h> |
24 | #include <linux/init.h> | ||
25 | #include <linux/cpu.h> | ||
26 | #include <linux/smp.h> | ||
27 | |||
27 | #include <asm/apic.h> | 28 | #include <asm/apic.h> |
29 | #include <asm/idle.h> | ||
28 | #include <asm/mce.h> | 30 | #include <asm/mce.h> |
29 | #include <asm/msr.h> | 31 | #include <asm/msr.h> |
30 | #include <asm/percpu.h> | ||
31 | #include <asm/idle.h> | ||
32 | 32 | ||
33 | #define PFX "mce_threshold: " | 33 | #define PFX "mce_threshold: " |
34 | #define VERSION "version 1.1.1" | 34 | #define VERSION "version 1.1.1" |
@@ -48,26 +48,26 @@ | |||
48 | #define MCG_XBLK_ADDR 0xC0000400 | 48 | #define MCG_XBLK_ADDR 0xC0000400 |
49 | 49 | ||
50 | struct threshold_block { | 50 | struct threshold_block { |
51 | unsigned int block; | 51 | unsigned int block; |
52 | unsigned int bank; | 52 | unsigned int bank; |
53 | unsigned int cpu; | 53 | unsigned int cpu; |
54 | u32 address; | 54 | u32 address; |
55 | u16 interrupt_enable; | 55 | u16 interrupt_enable; |
56 | u16 threshold_limit; | 56 | u16 threshold_limit; |
57 | struct kobject kobj; | 57 | struct kobject kobj; |
58 | struct list_head miscj; | 58 | struct list_head miscj; |
59 | }; | 59 | }; |
60 | 60 | ||
61 | /* defaults used early on boot */ | 61 | /* defaults used early on boot */ |
62 | static struct threshold_block threshold_defaults = { | 62 | static struct threshold_block threshold_defaults = { |
63 | .interrupt_enable = 0, | 63 | .interrupt_enable = 0, |
64 | .threshold_limit = THRESHOLD_MAX, | 64 | .threshold_limit = THRESHOLD_MAX, |
65 | }; | 65 | }; |
66 | 66 | ||
67 | struct threshold_bank { | 67 | struct threshold_bank { |
68 | struct kobject *kobj; | 68 | struct kobject *kobj; |
69 | struct threshold_block *blocks; | 69 | struct threshold_block *blocks; |
70 | cpumask_var_t cpus; | 70 | cpumask_var_t cpus; |
71 | }; | 71 | }; |
72 | static DEFINE_PER_CPU(struct threshold_bank *, threshold_banks[NR_BANKS]); | 72 | static DEFINE_PER_CPU(struct threshold_bank *, threshold_banks[NR_BANKS]); |
73 | 73 | ||
@@ -86,9 +86,9 @@ static void amd_threshold_interrupt(void); | |||
86 | */ | 86 | */ |
87 | 87 | ||
88 | struct thresh_restart { | 88 | struct thresh_restart { |
89 | struct threshold_block *b; | 89 | struct threshold_block *b; |
90 | int reset; | 90 | int reset; |
91 | u16 old_limit; | 91 | u16 old_limit; |
92 | }; | 92 | }; |
93 | 93 | ||
94 | /* must be called with correct cpu affinity */ | 94 | /* must be called with correct cpu affinity */ |
@@ -110,6 +110,7 @@ static void threshold_restart_bank(void *_tr) | |||
110 | } else if (tr->old_limit) { /* change limit w/o reset */ | 110 | } else if (tr->old_limit) { /* change limit w/o reset */ |
111 | int new_count = (mci_misc_hi & THRESHOLD_MAX) + | 111 | int new_count = (mci_misc_hi & THRESHOLD_MAX) + |
112 | (tr->old_limit - tr->b->threshold_limit); | 112 | (tr->old_limit - tr->b->threshold_limit); |
113 | |||
113 | mci_misc_hi = (mci_misc_hi & ~MASK_ERR_COUNT_HI) | | 114 | mci_misc_hi = (mci_misc_hi & ~MASK_ERR_COUNT_HI) | |
114 | (new_count & THRESHOLD_MAX); | 115 | (new_count & THRESHOLD_MAX); |
115 | } | 116 | } |
@@ -125,11 +126,11 @@ static void threshold_restart_bank(void *_tr) | |||
125 | /* cpu init entry point, called from mce.c with preempt off */ | 126 | /* cpu init entry point, called from mce.c with preempt off */ |
126 | void mce_amd_feature_init(struct cpuinfo_x86 *c) | 127 | void mce_amd_feature_init(struct cpuinfo_x86 *c) |
127 | { | 128 | { |
128 | unsigned int bank, block; | ||
129 | unsigned int cpu = smp_processor_id(); | 129 | unsigned int cpu = smp_processor_id(); |
130 | u8 lvt_off; | ||
131 | u32 low = 0, high = 0, address = 0; | 130 | u32 low = 0, high = 0, address = 0; |
131 | unsigned int bank, block; | ||
132 | struct thresh_restart tr; | 132 | struct thresh_restart tr; |
133 | u8 lvt_off; | ||
133 | 134 | ||
134 | for (bank = 0; bank < NR_BANKS; ++bank) { | 135 | for (bank = 0; bank < NR_BANKS; ++bank) { |
135 | for (block = 0; block < NR_BLOCKS; ++block) { | 136 | for (block = 0; block < NR_BLOCKS; ++block) { |
@@ -140,8 +141,7 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c) | |||
140 | if (!address) | 141 | if (!address) |
141 | break; | 142 | break; |
142 | address += MCG_XBLK_ADDR; | 143 | address += MCG_XBLK_ADDR; |
143 | } | 144 | } else |
144 | else | ||
145 | ++address; | 145 | ++address; |
146 | 146 | ||
147 | if (rdmsr_safe(address, &low, &high)) | 147 | if (rdmsr_safe(address, &low, &high)) |
@@ -193,9 +193,9 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c) | |||
193 | */ | 193 | */ |
194 | static void amd_threshold_interrupt(void) | 194 | static void amd_threshold_interrupt(void) |
195 | { | 195 | { |
196 | u32 low = 0, high = 0, address = 0; | ||
196 | unsigned int bank, block; | 197 | unsigned int bank, block; |
197 | struct mce m; | 198 | struct mce m; |
198 | u32 low = 0, high = 0, address = 0; | ||
199 | 199 | ||
200 | mce_setup(&m); | 200 | mce_setup(&m); |
201 | 201 | ||
@@ -204,16 +204,16 @@ static void amd_threshold_interrupt(void) | |||
204 | if (!(per_cpu(bank_map, m.cpu) & (1 << bank))) | 204 | if (!(per_cpu(bank_map, m.cpu) & (1 << bank))) |
205 | continue; | 205 | continue; |
206 | for (block = 0; block < NR_BLOCKS; ++block) { | 206 | for (block = 0; block < NR_BLOCKS; ++block) { |
207 | if (block == 0) | 207 | if (block == 0) { |
208 | address = MSR_IA32_MC0_MISC + bank * 4; | 208 | address = MSR_IA32_MC0_MISC + bank * 4; |
209 | else if (block == 1) { | 209 | } else if (block == 1) { |
210 | address = (low & MASK_BLKPTR_LO) >> 21; | 210 | address = (low & MASK_BLKPTR_LO) >> 21; |
211 | if (!address) | 211 | if (!address) |
212 | break; | 212 | break; |
213 | address += MCG_XBLK_ADDR; | 213 | address += MCG_XBLK_ADDR; |
214 | } | 214 | } else { |
215 | else | ||
216 | ++address; | 215 | ++address; |
216 | } | ||
217 | 217 | ||
218 | if (rdmsr_safe(address, &low, &high)) | 218 | if (rdmsr_safe(address, &low, &high)) |
219 | break; | 219 | break; |
@@ -229,8 +229,10 @@ static void amd_threshold_interrupt(void) | |||
229 | (high & MASK_LOCKED_HI)) | 229 | (high & MASK_LOCKED_HI)) |
230 | continue; | 230 | continue; |
231 | 231 | ||
232 | /* Log the machine check that caused the threshold | 232 | /* |
233 | event. */ | 233 | * Log the machine check that caused the threshold |
234 | * event. | ||
235 | */ | ||
234 | machine_check_poll(MCP_TIMESTAMP, | 236 | machine_check_poll(MCP_TIMESTAMP, |
235 | &__get_cpu_var(mce_poll_banks)); | 237 | &__get_cpu_var(mce_poll_banks)); |
236 | 238 | ||
@@ -254,48 +256,52 @@ static void amd_threshold_interrupt(void) | |||
254 | 256 | ||
255 | struct threshold_attr { | 257 | struct threshold_attr { |
256 | struct attribute attr; | 258 | struct attribute attr; |
257 | ssize_t(*show) (struct threshold_block *, char *); | 259 | ssize_t (*show) (struct threshold_block *, char *); |
258 | ssize_t(*store) (struct threshold_block *, const char *, size_t count); | 260 | ssize_t (*store) (struct threshold_block *, const char *, size_t count); |
259 | }; | 261 | }; |
260 | 262 | ||
261 | #define SHOW_FIELDS(name) \ | 263 | #define SHOW_FIELDS(name) \ |
262 | static ssize_t show_ ## name(struct threshold_block * b, char *buf) \ | 264 | static ssize_t show_ ## name(struct threshold_block *b, char *buf) \ |
263 | { \ | 265 | { \ |
264 | return sprintf(buf, "%lx\n", (unsigned long) b->name); \ | 266 | return sprintf(buf, "%lx\n", (unsigned long) b->name); \ |
265 | } | 267 | } |
266 | SHOW_FIELDS(interrupt_enable) | 268 | SHOW_FIELDS(interrupt_enable) |
267 | SHOW_FIELDS(threshold_limit) | 269 | SHOW_FIELDS(threshold_limit) |
268 | 270 | ||
269 | static ssize_t store_interrupt_enable(struct threshold_block *b, | 271 | static ssize_t |
270 | const char *buf, size_t count) | 272 | store_interrupt_enable(struct threshold_block *b, const char *buf, size_t size) |
271 | { | 273 | { |
272 | char *end; | ||
273 | struct thresh_restart tr; | 274 | struct thresh_restart tr; |
274 | unsigned long new = simple_strtoul(buf, &end, 0); | 275 | unsigned long new; |
275 | if (end == buf) | 276 | |
277 | if (strict_strtoul(buf, 0, &new) < 0) | ||
276 | return -EINVAL; | 278 | return -EINVAL; |
279 | |||
277 | b->interrupt_enable = !!new; | 280 | b->interrupt_enable = !!new; |
278 | 281 | ||
279 | tr.b = b; | 282 | tr.b = b; |
280 | tr.reset = 0; | 283 | tr.reset = 0; |
281 | tr.old_limit = 0; | 284 | tr.old_limit = 0; |
285 | |||
282 | smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1); | 286 | smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1); |
283 | 287 | ||
284 | return end - buf; | 288 | return size; |
285 | } | 289 | } |
286 | 290 | ||
287 | static ssize_t store_threshold_limit(struct threshold_block *b, | 291 | static ssize_t |
288 | const char *buf, size_t count) | 292 | store_threshold_limit(struct threshold_block *b, const char *buf, size_t size) |
289 | { | 293 | { |
290 | char *end; | ||
291 | struct thresh_restart tr; | 294 | struct thresh_restart tr; |
292 | unsigned long new = simple_strtoul(buf, &end, 0); | 295 | unsigned long new; |
293 | if (end == buf) | 296 | |
297 | if (strict_strtoul(buf, 0, &new) < 0) | ||
294 | return -EINVAL; | 298 | return -EINVAL; |
299 | |||
295 | if (new > THRESHOLD_MAX) | 300 | if (new > THRESHOLD_MAX) |
296 | new = THRESHOLD_MAX; | 301 | new = THRESHOLD_MAX; |
297 | if (new < 1) | 302 | if (new < 1) |
298 | new = 1; | 303 | new = 1; |
304 | |||
299 | tr.old_limit = b->threshold_limit; | 305 | tr.old_limit = b->threshold_limit; |
300 | b->threshold_limit = new; | 306 | b->threshold_limit = new; |
301 | tr.b = b; | 307 | tr.b = b; |
@@ -303,12 +309,12 @@ static ssize_t store_threshold_limit(struct threshold_block *b, | |||
303 | 309 | ||
304 | smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1); | 310 | smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1); |
305 | 311 | ||
306 | return end - buf; | 312 | return size; |
307 | } | 313 | } |
308 | 314 | ||
309 | struct threshold_block_cross_cpu { | 315 | struct threshold_block_cross_cpu { |
310 | struct threshold_block *tb; | 316 | struct threshold_block *tb; |
311 | long retval; | 317 | long retval; |
312 | }; | 318 | }; |
313 | 319 | ||
314 | static void local_error_count_handler(void *_tbcc) | 320 | static void local_error_count_handler(void *_tbcc) |
@@ -338,16 +344,13 @@ static ssize_t store_error_count(struct threshold_block *b, | |||
338 | return 1; | 344 | return 1; |
339 | } | 345 | } |
340 | 346 | ||
341 | #define THRESHOLD_ATTR(_name,_mode,_show,_store) { \ | 347 | #define RW_ATTR(val) \ |
342 | .attr = {.name = __stringify(_name), .mode = _mode }, \ | 348 | static struct threshold_attr val = { \ |
343 | .show = _show, \ | 349 | .attr = {.name = __stringify(val), .mode = 0644 }, \ |
344 | .store = _store, \ | 350 | .show = show_## val, \ |
351 | .store = store_## val, \ | ||
345 | }; | 352 | }; |
346 | 353 | ||
347 | #define RW_ATTR(name) \ | ||
348 | static struct threshold_attr name = \ | ||
349 | THRESHOLD_ATTR(name, 0644, show_## name, store_## name) | ||
350 | |||
351 | RW_ATTR(interrupt_enable); | 354 | RW_ATTR(interrupt_enable); |
352 | RW_ATTR(threshold_limit); | 355 | RW_ATTR(threshold_limit); |
353 | RW_ATTR(error_count); | 356 | RW_ATTR(error_count); |
@@ -359,15 +362,17 @@ static struct attribute *default_attrs[] = { | |||
359 | NULL | 362 | NULL |
360 | }; | 363 | }; |
361 | 364 | ||
362 | #define to_block(k) container_of(k, struct threshold_block, kobj) | 365 | #define to_block(k) container_of(k, struct threshold_block, kobj) |
363 | #define to_attr(a) container_of(a, struct threshold_attr, attr) | 366 | #define to_attr(a) container_of(a, struct threshold_attr, attr) |
364 | 367 | ||
365 | static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf) | 368 | static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf) |
366 | { | 369 | { |
367 | struct threshold_block *b = to_block(kobj); | 370 | struct threshold_block *b = to_block(kobj); |
368 | struct threshold_attr *a = to_attr(attr); | 371 | struct threshold_attr *a = to_attr(attr); |
369 | ssize_t ret; | 372 | ssize_t ret; |
373 | |||
370 | ret = a->show ? a->show(b, buf) : -EIO; | 374 | ret = a->show ? a->show(b, buf) : -EIO; |
375 | |||
371 | return ret; | 376 | return ret; |
372 | } | 377 | } |
373 | 378 | ||
@@ -377,18 +382,20 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr, | |||
377 | struct threshold_block *b = to_block(kobj); | 382 | struct threshold_block *b = to_block(kobj); |
378 | struct threshold_attr *a = to_attr(attr); | 383 | struct threshold_attr *a = to_attr(attr); |
379 | ssize_t ret; | 384 | ssize_t ret; |
385 | |||
380 | ret = a->store ? a->store(b, buf, count) : -EIO; | 386 | ret = a->store ? a->store(b, buf, count) : -EIO; |
387 | |||
381 | return ret; | 388 | return ret; |
382 | } | 389 | } |
383 | 390 | ||
384 | static struct sysfs_ops threshold_ops = { | 391 | static struct sysfs_ops threshold_ops = { |
385 | .show = show, | 392 | .show = show, |
386 | .store = store, | 393 | .store = store, |
387 | }; | 394 | }; |
388 | 395 | ||
389 | static struct kobj_type threshold_ktype = { | 396 | static struct kobj_type threshold_ktype = { |
390 | .sysfs_ops = &threshold_ops, | 397 | .sysfs_ops = &threshold_ops, |
391 | .default_attrs = default_attrs, | 398 | .default_attrs = default_attrs, |
392 | }; | 399 | }; |
393 | 400 | ||
394 | static __cpuinit int allocate_threshold_blocks(unsigned int cpu, | 401 | static __cpuinit int allocate_threshold_blocks(unsigned int cpu, |
@@ -396,9 +403,9 @@ static __cpuinit int allocate_threshold_blocks(unsigned int cpu, | |||
396 | unsigned int block, | 403 | unsigned int block, |
397 | u32 address) | 404 | u32 address) |
398 | { | 405 | { |
399 | int err; | ||
400 | u32 low, high; | ||
401 | struct threshold_block *b = NULL; | 406 | struct threshold_block *b = NULL; |
407 | u32 low, high; | ||
408 | int err; | ||
402 | 409 | ||
403 | if ((bank >= NR_BANKS) || (block >= NR_BLOCKS)) | 410 | if ((bank >= NR_BANKS) || (block >= NR_BLOCKS)) |
404 | return 0; | 411 | return 0; |
@@ -421,20 +428,21 @@ static __cpuinit int allocate_threshold_blocks(unsigned int cpu, | |||
421 | if (!b) | 428 | if (!b) |
422 | return -ENOMEM; | 429 | return -ENOMEM; |
423 | 430 | ||
424 | b->block = block; | 431 | b->block = block; |
425 | b->bank = bank; | 432 | b->bank = bank; |
426 | b->cpu = cpu; | 433 | b->cpu = cpu; |
427 | b->address = address; | 434 | b->address = address; |
428 | b->interrupt_enable = 0; | 435 | b->interrupt_enable = 0; |
429 | b->threshold_limit = THRESHOLD_MAX; | 436 | b->threshold_limit = THRESHOLD_MAX; |
430 | 437 | ||
431 | INIT_LIST_HEAD(&b->miscj); | 438 | INIT_LIST_HEAD(&b->miscj); |
432 | 439 | ||
433 | if (per_cpu(threshold_banks, cpu)[bank]->blocks) | 440 | if (per_cpu(threshold_banks, cpu)[bank]->blocks) { |
434 | list_add(&b->miscj, | 441 | list_add(&b->miscj, |
435 | &per_cpu(threshold_banks, cpu)[bank]->blocks->miscj); | 442 | &per_cpu(threshold_banks, cpu)[bank]->blocks->miscj); |
436 | else | 443 | } else { |
437 | per_cpu(threshold_banks, cpu)[bank]->blocks = b; | 444 | per_cpu(threshold_banks, cpu)[bank]->blocks = b; |
445 | } | ||
438 | 446 | ||
439 | err = kobject_init_and_add(&b->kobj, &threshold_ktype, | 447 | err = kobject_init_and_add(&b->kobj, &threshold_ktype, |
440 | per_cpu(threshold_banks, cpu)[bank]->kobj, | 448 | per_cpu(threshold_banks, cpu)[bank]->kobj, |
@@ -447,8 +455,9 @@ recurse: | |||
447 | if (!address) | 455 | if (!address) |
448 | return 0; | 456 | return 0; |
449 | address += MCG_XBLK_ADDR; | 457 | address += MCG_XBLK_ADDR; |
450 | } else | 458 | } else { |
451 | ++address; | 459 | ++address; |
460 | } | ||
452 | 461 | ||
453 | err = allocate_threshold_blocks(cpu, bank, ++block, address); | 462 | err = allocate_threshold_blocks(cpu, bank, ++block, address); |
454 | if (err) | 463 | if (err) |
@@ -500,13 +509,14 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) | |||
500 | if (!b) | 509 | if (!b) |
501 | goto out; | 510 | goto out; |
502 | 511 | ||
503 | err = sysfs_create_link(&per_cpu(device_mce, cpu).kobj, | 512 | err = sysfs_create_link(&per_cpu(mce_dev, cpu).kobj, |
504 | b->kobj, name); | 513 | b->kobj, name); |
505 | if (err) | 514 | if (err) |
506 | goto out; | 515 | goto out; |
507 | 516 | ||
508 | cpumask_copy(b->cpus, cpu_core_mask(cpu)); | 517 | cpumask_copy(b->cpus, cpu_core_mask(cpu)); |
509 | per_cpu(threshold_banks, cpu)[bank] = b; | 518 | per_cpu(threshold_banks, cpu)[bank] = b; |
519 | |||
510 | goto out; | 520 | goto out; |
511 | } | 521 | } |
512 | #endif | 522 | #endif |
@@ -522,7 +532,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) | |||
522 | goto out; | 532 | goto out; |
523 | } | 533 | } |
524 | 534 | ||
525 | b->kobj = kobject_create_and_add(name, &per_cpu(device_mce, cpu).kobj); | 535 | b->kobj = kobject_create_and_add(name, &per_cpu(mce_dev, cpu).kobj); |
526 | if (!b->kobj) | 536 | if (!b->kobj) |
527 | goto out_free; | 537 | goto out_free; |
528 | 538 | ||
@@ -542,7 +552,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) | |||
542 | if (i == cpu) | 552 | if (i == cpu) |
543 | continue; | 553 | continue; |
544 | 554 | ||
545 | err = sysfs_create_link(&per_cpu(device_mce, i).kobj, | 555 | err = sysfs_create_link(&per_cpu(mce_dev, i).kobj, |
546 | b->kobj, name); | 556 | b->kobj, name); |
547 | if (err) | 557 | if (err) |
548 | goto out; | 558 | goto out; |
@@ -605,15 +615,13 @@ static void deallocate_threshold_block(unsigned int cpu, | |||
605 | 615 | ||
606 | static void threshold_remove_bank(unsigned int cpu, int bank) | 616 | static void threshold_remove_bank(unsigned int cpu, int bank) |
607 | { | 617 | { |
608 | int i = 0; | ||
609 | struct threshold_bank *b; | 618 | struct threshold_bank *b; |
610 | char name[32]; | 619 | char name[32]; |
620 | int i = 0; | ||
611 | 621 | ||
612 | b = per_cpu(threshold_banks, cpu)[bank]; | 622 | b = per_cpu(threshold_banks, cpu)[bank]; |
613 | |||
614 | if (!b) | 623 | if (!b) |
615 | return; | 624 | return; |
616 | |||
617 | if (!b->blocks) | 625 | if (!b->blocks) |
618 | goto free_out; | 626 | goto free_out; |
619 | 627 | ||
@@ -622,8 +630,9 @@ static void threshold_remove_bank(unsigned int cpu, int bank) | |||
622 | #ifdef CONFIG_SMP | 630 | #ifdef CONFIG_SMP |
623 | /* sibling symlink */ | 631 | /* sibling symlink */ |
624 | if (shared_bank[bank] && b->blocks->cpu != cpu) { | 632 | if (shared_bank[bank] && b->blocks->cpu != cpu) { |
625 | sysfs_remove_link(&per_cpu(device_mce, cpu).kobj, name); | 633 | sysfs_remove_link(&per_cpu(mce_dev, cpu).kobj, name); |
626 | per_cpu(threshold_banks, cpu)[bank] = NULL; | 634 | per_cpu(threshold_banks, cpu)[bank] = NULL; |
635 | |||
627 | return; | 636 | return; |
628 | } | 637 | } |
629 | #endif | 638 | #endif |
@@ -633,7 +642,7 @@ static void threshold_remove_bank(unsigned int cpu, int bank) | |||
633 | if (i == cpu) | 642 | if (i == cpu) |
634 | continue; | 643 | continue; |
635 | 644 | ||
636 | sysfs_remove_link(&per_cpu(device_mce, i).kobj, name); | 645 | sysfs_remove_link(&per_cpu(mce_dev, i).kobj, name); |
637 | per_cpu(threshold_banks, i)[bank] = NULL; | 646 | per_cpu(threshold_banks, i)[bank] = NULL; |
638 | } | 647 | } |
639 | 648 | ||
@@ -659,12 +668,9 @@ static void threshold_remove_device(unsigned int cpu) | |||
659 | } | 668 | } |
660 | 669 | ||
661 | /* get notified when a cpu comes on/off */ | 670 | /* get notified when a cpu comes on/off */ |
662 | static void __cpuinit amd_64_threshold_cpu_callback(unsigned long action, | 671 | static void __cpuinit |
663 | unsigned int cpu) | 672 | amd_64_threshold_cpu_callback(unsigned long action, unsigned int cpu) |
664 | { | 673 | { |
665 | if (cpu >= NR_CPUS) | ||
666 | return; | ||
667 | |||
668 | switch (action) { | 674 | switch (action) { |
669 | case CPU_ONLINE: | 675 | case CPU_ONLINE: |
670 | case CPU_ONLINE_FROZEN: | 676 | case CPU_ONLINE_FROZEN: |
@@ -686,11 +692,12 @@ static __init int threshold_init_device(void) | |||
686 | /* to hit CPUs online before the notifier is up */ | 692 | /* to hit CPUs online before the notifier is up */ |
687 | for_each_online_cpu(lcpu) { | 693 | for_each_online_cpu(lcpu) { |
688 | int err = threshold_create_device(lcpu); | 694 | int err = threshold_create_device(lcpu); |
695 | |||
689 | if (err) | 696 | if (err) |
690 | return err; | 697 | return err; |
691 | } | 698 | } |
692 | threshold_cpu_callback = amd_64_threshold_cpu_callback; | 699 | threshold_cpu_callback = amd_64_threshold_cpu_callback; |
700 | |||
693 | return 0; | 701 | return 0; |
694 | } | 702 | } |
695 | |||
696 | device_initcall(threshold_init_device); | 703 | device_initcall(threshold_init_device); |
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel.c b/arch/x86/kernel/cpu/mcheck/mce_intel.c new file mode 100644 index 000000000000..2b011d2d8579 --- /dev/null +++ b/arch/x86/kernel/cpu/mcheck/mce_intel.c | |||
@@ -0,0 +1,74 @@ | |||
1 | /* | ||
2 | * Common code for Intel machine checks | ||
3 | */ | ||
4 | #include <linux/interrupt.h> | ||
5 | #include <linux/kernel.h> | ||
6 | #include <linux/types.h> | ||
7 | #include <linux/init.h> | ||
8 | #include <linux/smp.h> | ||
9 | |||
10 | #include <asm/therm_throt.h> | ||
11 | #include <asm/processor.h> | ||
12 | #include <asm/system.h> | ||
13 | #include <asm/apic.h> | ||
14 | #include <asm/msr.h> | ||
15 | |||
16 | #include "mce.h" | ||
17 | |||
18 | void intel_init_thermal(struct cpuinfo_x86 *c) | ||
19 | { | ||
20 | unsigned int cpu = smp_processor_id(); | ||
21 | int tm2 = 0; | ||
22 | u32 l, h; | ||
23 | |||
24 | /* Thermal monitoring depends on ACPI and clock modulation*/ | ||
25 | if (!cpu_has(c, X86_FEATURE_ACPI) || !cpu_has(c, X86_FEATURE_ACC)) | ||
26 | return; | ||
27 | |||
28 | /* | ||
29 | * First check if its enabled already, in which case there might | ||
30 | * be some SMM goo which handles it, so we can't even put a handler | ||
31 | * since it might be delivered via SMI already: | ||
32 | */ | ||
33 | rdmsr(MSR_IA32_MISC_ENABLE, l, h); | ||
34 | h = apic_read(APIC_LVTTHMR); | ||
35 | if ((l & MSR_IA32_MISC_ENABLE_TM1) && (h & APIC_DM_SMI)) { | ||
36 | printk(KERN_DEBUG | ||
37 | "CPU%d: Thermal monitoring handled by SMI\n", cpu); | ||
38 | return; | ||
39 | } | ||
40 | |||
41 | if (cpu_has(c, X86_FEATURE_TM2) && (l & MSR_IA32_MISC_ENABLE_TM2)) | ||
42 | tm2 = 1; | ||
43 | |||
44 | /* Check whether a vector already exists */ | ||
45 | if (h & APIC_VECTOR_MASK) { | ||
46 | printk(KERN_DEBUG | ||
47 | "CPU%d: Thermal LVT vector (%#x) already installed\n", | ||
48 | cpu, (h & APIC_VECTOR_MASK)); | ||
49 | return; | ||
50 | } | ||
51 | |||
52 | /* We'll mask the thermal vector in the lapic till we're ready: */ | ||
53 | h = THERMAL_APIC_VECTOR | APIC_DM_FIXED | APIC_LVT_MASKED; | ||
54 | apic_write(APIC_LVTTHMR, h); | ||
55 | |||
56 | rdmsr(MSR_IA32_THERM_INTERRUPT, l, h); | ||
57 | wrmsr(MSR_IA32_THERM_INTERRUPT, | ||
58 | l | (THERM_INT_LOW_ENABLE | THERM_INT_HIGH_ENABLE), h); | ||
59 | |||
60 | intel_set_thermal_handler(); | ||
61 | |||
62 | rdmsr(MSR_IA32_MISC_ENABLE, l, h); | ||
63 | wrmsr(MSR_IA32_MISC_ENABLE, l | MSR_IA32_MISC_ENABLE_TM1, h); | ||
64 | |||
65 | /* Unmask the thermal vector: */ | ||
66 | l = apic_read(APIC_LVTTHMR); | ||
67 | apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED); | ||
68 | |||
69 | printk(KERN_INFO "CPU%d: Thermal monitoring enabled (%s)\n", | ||
70 | cpu, tm2 ? "TM2" : "TM1"); | ||
71 | |||
72 | /* enable thermal throttle processing */ | ||
73 | atomic_set(&therm_throt_en, 1); | ||
74 | } | ||
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel_64.c b/arch/x86/kernel/cpu/mcheck/mce_intel_64.c index 65a0fceedcd7..f2ef6952c400 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_intel_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_intel_64.c | |||
@@ -16,6 +16,8 @@ | |||
16 | #include <asm/idle.h> | 16 | #include <asm/idle.h> |
17 | #include <asm/therm_throt.h> | 17 | #include <asm/therm_throt.h> |
18 | 18 | ||
19 | #include "mce.h" | ||
20 | |||
19 | asmlinkage void smp_thermal_interrupt(void) | 21 | asmlinkage void smp_thermal_interrupt(void) |
20 | { | 22 | { |
21 | __u64 msr_val; | 23 | __u64 msr_val; |
@@ -26,67 +28,13 @@ asmlinkage void smp_thermal_interrupt(void) | |||
26 | irq_enter(); | 28 | irq_enter(); |
27 | 29 | ||
28 | rdmsrl(MSR_IA32_THERM_STATUS, msr_val); | 30 | rdmsrl(MSR_IA32_THERM_STATUS, msr_val); |
29 | if (therm_throt_process(msr_val & 1)) | 31 | if (therm_throt_process(msr_val & THERM_STATUS_PROCHOT)) |
30 | mce_log_therm_throt_event(msr_val); | 32 | mce_log_therm_throt_event(msr_val); |
31 | 33 | ||
32 | inc_irq_stat(irq_thermal_count); | 34 | inc_irq_stat(irq_thermal_count); |
33 | irq_exit(); | 35 | irq_exit(); |
34 | } | 36 | } |
35 | 37 | ||
36 | static void intel_init_thermal(struct cpuinfo_x86 *c) | ||
37 | { | ||
38 | u32 l, h; | ||
39 | int tm2 = 0; | ||
40 | unsigned int cpu = smp_processor_id(); | ||
41 | |||
42 | if (!cpu_has(c, X86_FEATURE_ACPI)) | ||
43 | return; | ||
44 | |||
45 | if (!cpu_has(c, X86_FEATURE_ACC)) | ||
46 | return; | ||
47 | |||
48 | /* first check if TM1 is already enabled by the BIOS, in which | ||
49 | * case there might be some SMM goo which handles it, so we can't even | ||
50 | * put a handler since it might be delivered via SMI already. | ||
51 | */ | ||
52 | rdmsr(MSR_IA32_MISC_ENABLE, l, h); | ||
53 | h = apic_read(APIC_LVTTHMR); | ||
54 | if ((l & MSR_IA32_MISC_ENABLE_TM1) && (h & APIC_DM_SMI)) { | ||
55 | printk(KERN_DEBUG | ||
56 | "CPU%d: Thermal monitoring handled by SMI\n", cpu); | ||
57 | return; | ||
58 | } | ||
59 | |||
60 | if (cpu_has(c, X86_FEATURE_TM2) && (l & MSR_IA32_MISC_ENABLE_TM2)) | ||
61 | tm2 = 1; | ||
62 | |||
63 | if (h & APIC_VECTOR_MASK) { | ||
64 | printk(KERN_DEBUG | ||
65 | "CPU%d: Thermal LVT vector (%#x) already " | ||
66 | "installed\n", cpu, (h & APIC_VECTOR_MASK)); | ||
67 | return; | ||
68 | } | ||
69 | |||
70 | h = THERMAL_APIC_VECTOR; | ||
71 | h |= (APIC_DM_FIXED | APIC_LVT_MASKED); | ||
72 | apic_write(APIC_LVTTHMR, h); | ||
73 | |||
74 | rdmsr(MSR_IA32_THERM_INTERRUPT, l, h); | ||
75 | wrmsr(MSR_IA32_THERM_INTERRUPT, l | 0x03, h); | ||
76 | |||
77 | rdmsr(MSR_IA32_MISC_ENABLE, l, h); | ||
78 | wrmsr(MSR_IA32_MISC_ENABLE, l | MSR_IA32_MISC_ENABLE_TM1, h); | ||
79 | |||
80 | l = apic_read(APIC_LVTTHMR); | ||
81 | apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED); | ||
82 | printk(KERN_INFO "CPU%d: Thermal monitoring enabled (%s)\n", | ||
83 | cpu, tm2 ? "TM2" : "TM1"); | ||
84 | |||
85 | /* enable thermal throttle processing */ | ||
86 | atomic_set(&therm_throt_en, 1); | ||
87 | return; | ||
88 | } | ||
89 | |||
90 | /* | 38 | /* |
91 | * Support for Intel Correct Machine Check Interrupts. This allows | 39 | * Support for Intel Correct Machine Check Interrupts. This allows |
92 | * the CPU to raise an interrupt when a corrected machine check happened. | 40 | * the CPU to raise an interrupt when a corrected machine check happened. |
@@ -108,6 +56,9 @@ static int cmci_supported(int *banks) | |||
108 | { | 56 | { |
109 | u64 cap; | 57 | u64 cap; |
110 | 58 | ||
59 | if (mce_cmci_disabled || mce_ignore_ce) | ||
60 | return 0; | ||
61 | |||
111 | /* | 62 | /* |
112 | * Vendor check is not strictly needed, but the initial | 63 | * Vendor check is not strictly needed, but the initial |
113 | * initialization is vendor keyed and this | 64 | * initialization is vendor keyed and this |
@@ -131,7 +82,7 @@ static int cmci_supported(int *banks) | |||
131 | static void intel_threshold_interrupt(void) | 82 | static void intel_threshold_interrupt(void) |
132 | { | 83 | { |
133 | machine_check_poll(MCP_TIMESTAMP, &__get_cpu_var(mce_banks_owned)); | 84 | machine_check_poll(MCP_TIMESTAMP, &__get_cpu_var(mce_banks_owned)); |
134 | mce_notify_user(); | 85 | mce_notify_irq(); |
135 | } | 86 | } |
136 | 87 | ||
137 | static void print_update(char *type, int *hdr, int num) | 88 | static void print_update(char *type, int *hdr, int num) |
@@ -247,7 +198,7 @@ void cmci_rediscover(int dying) | |||
247 | return; | 198 | return; |
248 | cpumask_copy(old, ¤t->cpus_allowed); | 199 | cpumask_copy(old, ¤t->cpus_allowed); |
249 | 200 | ||
250 | for_each_online_cpu (cpu) { | 201 | for_each_online_cpu(cpu) { |
251 | if (cpu == dying) | 202 | if (cpu == dying) |
252 | continue; | 203 | continue; |
253 | if (set_cpus_allowed_ptr(current, cpumask_of(cpu))) | 204 | if (set_cpus_allowed_ptr(current, cpumask_of(cpu))) |
diff --git a/arch/x86/kernel/cpu/mcheck/non-fatal.c b/arch/x86/kernel/cpu/mcheck/non-fatal.c index a74af128efc9..70b710420f74 100644 --- a/arch/x86/kernel/cpu/mcheck/non-fatal.c +++ b/arch/x86/kernel/cpu/mcheck/non-fatal.c | |||
@@ -6,15 +6,14 @@ | |||
6 | * This file contains routines to check for non-fatal MCEs every 15s | 6 | * This file contains routines to check for non-fatal MCEs every 15s |
7 | * | 7 | * |
8 | */ | 8 | */ |
9 | |||
10 | #include <linux/init.h> | ||
11 | #include <linux/types.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/jiffies.h> | ||
14 | #include <linux/workqueue.h> | ||
15 | #include <linux/interrupt.h> | 9 | #include <linux/interrupt.h> |
16 | #include <linux/smp.h> | 10 | #include <linux/workqueue.h> |
11 | #include <linux/jiffies.h> | ||
12 | #include <linux/kernel.h> | ||
17 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/types.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/smp.h> | ||
18 | 17 | ||
19 | #include <asm/processor.h> | 18 | #include <asm/processor.h> |
20 | #include <asm/system.h> | 19 | #include <asm/system.h> |
@@ -22,9 +21,9 @@ | |||
22 | 21 | ||
23 | #include "mce.h" | 22 | #include "mce.h" |
24 | 23 | ||
25 | static int firstbank; | 24 | static int firstbank; |
26 | 25 | ||
27 | #define MCE_RATE 15*HZ /* timer rate is 15s */ | 26 | #define MCE_RATE (15*HZ) /* timer rate is 15s */ |
28 | 27 | ||
29 | static void mce_checkregs(void *info) | 28 | static void mce_checkregs(void *info) |
30 | { | 29 | { |
@@ -34,23 +33,24 @@ static void mce_checkregs(void *info) | |||
34 | for (i = firstbank; i < nr_mce_banks; i++) { | 33 | for (i = firstbank; i < nr_mce_banks; i++) { |
35 | rdmsr(MSR_IA32_MC0_STATUS+i*4, low, high); | 34 | rdmsr(MSR_IA32_MC0_STATUS+i*4, low, high); |
36 | 35 | ||
37 | if (high & (1<<31)) { | 36 | if (!(high & (1<<31))) |
38 | printk(KERN_INFO "MCE: The hardware reports a non " | 37 | continue; |
39 | "fatal, correctable incident occurred on " | 38 | |
40 | "CPU %d.\n", | 39 | printk(KERN_INFO "MCE: The hardware reports a non fatal, " |
40 | "correctable incident occurred on CPU %d.\n", | ||
41 | smp_processor_id()); | 41 | smp_processor_id()); |
42 | printk(KERN_INFO "Bank %d: %08x%08x\n", i, high, low); | 42 | |
43 | 43 | printk(KERN_INFO "Bank %d: %08x%08x\n", i, high, low); | |
44 | /* | 44 | |
45 | * Scrub the error so we don't pick it up in MCE_RATE | 45 | /* |
46 | * seconds time. | 46 | * Scrub the error so we don't pick it up in MCE_RATE |
47 | */ | 47 | * seconds time: |
48 | wrmsr(MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL); | 48 | */ |
49 | 49 | wrmsr(MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL); | |
50 | /* Serialize */ | 50 | |
51 | wmb(); | 51 | /* Serialize: */ |
52 | add_taint(TAINT_MACHINE_CHECK); | 52 | wmb(); |
53 | } | 53 | add_taint(TAINT_MACHINE_CHECK); |
54 | } | 54 | } |
55 | } | 55 | } |
56 | 56 | ||
@@ -77,16 +77,17 @@ static int __init init_nonfatal_mce_checker(void) | |||
77 | 77 | ||
78 | /* Some Athlons misbehave when we frob bank 0 */ | 78 | /* Some Athlons misbehave when we frob bank 0 */ |
79 | if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD && | 79 | if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD && |
80 | boot_cpu_data.x86 == 6) | 80 | boot_cpu_data.x86 == 6) |
81 | firstbank = 1; | 81 | firstbank = 1; |
82 | else | 82 | else |
83 | firstbank = 0; | 83 | firstbank = 0; |
84 | 84 | ||
85 | /* | 85 | /* |
86 | * Check for non-fatal errors every MCE_RATE s | 86 | * Check for non-fatal errors every MCE_RATE s |
87 | */ | 87 | */ |
88 | schedule_delayed_work(&mce_work, round_jiffies_relative(MCE_RATE)); | 88 | schedule_delayed_work(&mce_work, round_jiffies_relative(MCE_RATE)); |
89 | printk(KERN_INFO "Machine check exception polling timer started.\n"); | 89 | printk(KERN_INFO "Machine check exception polling timer started.\n"); |
90 | |||
90 | return 0; | 91 | return 0; |
91 | } | 92 | } |
92 | module_init(init_nonfatal_mce_checker); | 93 | module_init(init_nonfatal_mce_checker); |
diff --git a/arch/x86/kernel/cpu/mcheck/p4.c b/arch/x86/kernel/cpu/mcheck/p4.c index f53bdcbaf382..82cee108a2d3 100644 --- a/arch/x86/kernel/cpu/mcheck/p4.c +++ b/arch/x86/kernel/cpu/mcheck/p4.c | |||
@@ -2,18 +2,17 @@ | |||
2 | * P4 specific Machine Check Exception Reporting | 2 | * P4 specific Machine Check Exception Reporting |
3 | */ | 3 | */ |
4 | 4 | ||
5 | #include <linux/init.h> | ||
6 | #include <linux/types.h> | ||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/interrupt.h> | 5 | #include <linux/interrupt.h> |
6 | #include <linux/kernel.h> | ||
7 | #include <linux/types.h> | ||
8 | #include <linux/init.h> | ||
9 | #include <linux/smp.h> | 9 | #include <linux/smp.h> |
10 | 10 | ||
11 | #include <asm/therm_throt.h> | ||
11 | #include <asm/processor.h> | 12 | #include <asm/processor.h> |
12 | #include <asm/system.h> | 13 | #include <asm/system.h> |
13 | #include <asm/msr.h> | ||
14 | #include <asm/apic.h> | 14 | #include <asm/apic.h> |
15 | 15 | #include <asm/msr.h> | |
16 | #include <asm/therm_throt.h> | ||
17 | 16 | ||
18 | #include "mce.h" | 17 | #include "mce.h" |
19 | 18 | ||
@@ -36,6 +35,7 @@ static int mce_num_extended_msrs; | |||
36 | 35 | ||
37 | 36 | ||
38 | #ifdef CONFIG_X86_MCE_P4THERMAL | 37 | #ifdef CONFIG_X86_MCE_P4THERMAL |
38 | |||
39 | static void unexpected_thermal_interrupt(struct pt_regs *regs) | 39 | static void unexpected_thermal_interrupt(struct pt_regs *regs) |
40 | { | 40 | { |
41 | printk(KERN_ERR "CPU%d: Unexpected LVT TMR interrupt!\n", | 41 | printk(KERN_ERR "CPU%d: Unexpected LVT TMR interrupt!\n", |
@@ -43,7 +43,7 @@ static void unexpected_thermal_interrupt(struct pt_regs *regs) | |||
43 | add_taint(TAINT_MACHINE_CHECK); | 43 | add_taint(TAINT_MACHINE_CHECK); |
44 | } | 44 | } |
45 | 45 | ||
46 | /* P4/Xeon Thermal transition interrupt handler */ | 46 | /* P4/Xeon Thermal transition interrupt handler: */ |
47 | static void intel_thermal_interrupt(struct pt_regs *regs) | 47 | static void intel_thermal_interrupt(struct pt_regs *regs) |
48 | { | 48 | { |
49 | __u64 msr_val; | 49 | __u64 msr_val; |
@@ -51,11 +51,12 @@ static void intel_thermal_interrupt(struct pt_regs *regs) | |||
51 | ack_APIC_irq(); | 51 | ack_APIC_irq(); |
52 | 52 | ||
53 | rdmsrl(MSR_IA32_THERM_STATUS, msr_val); | 53 | rdmsrl(MSR_IA32_THERM_STATUS, msr_val); |
54 | therm_throt_process(msr_val & 0x1); | 54 | therm_throt_process(msr_val & THERM_STATUS_PROCHOT); |
55 | } | 55 | } |
56 | 56 | ||
57 | /* Thermal interrupt handler for this CPU setup */ | 57 | /* Thermal interrupt handler for this CPU setup: */ |
58 | static void (*vendor_thermal_interrupt)(struct pt_regs *regs) = unexpected_thermal_interrupt; | 58 | static void (*vendor_thermal_interrupt)(struct pt_regs *regs) = |
59 | unexpected_thermal_interrupt; | ||
59 | 60 | ||
60 | void smp_thermal_interrupt(struct pt_regs *regs) | 61 | void smp_thermal_interrupt(struct pt_regs *regs) |
61 | { | 62 | { |
@@ -65,67 +66,15 @@ void smp_thermal_interrupt(struct pt_regs *regs) | |||
65 | irq_exit(); | 66 | irq_exit(); |
66 | } | 67 | } |
67 | 68 | ||
68 | /* P4/Xeon Thermal regulation detect and init */ | 69 | void intel_set_thermal_handler(void) |
69 | static void intel_init_thermal(struct cpuinfo_x86 *c) | ||
70 | { | 70 | { |
71 | u32 l, h; | ||
72 | unsigned int cpu = smp_processor_id(); | ||
73 | |||
74 | /* Thermal monitoring */ | ||
75 | if (!cpu_has(c, X86_FEATURE_ACPI)) | ||
76 | return; /* -ENODEV */ | ||
77 | |||
78 | /* Clock modulation */ | ||
79 | if (!cpu_has(c, X86_FEATURE_ACC)) | ||
80 | return; /* -ENODEV */ | ||
81 | |||
82 | /* first check if its enabled already, in which case there might | ||
83 | * be some SMM goo which handles it, so we can't even put a handler | ||
84 | * since it might be delivered via SMI already -zwanem. | ||
85 | */ | ||
86 | rdmsr(MSR_IA32_MISC_ENABLE, l, h); | ||
87 | h = apic_read(APIC_LVTTHMR); | ||
88 | if ((l & MSR_IA32_MISC_ENABLE_TM1) && (h & APIC_DM_SMI)) { | ||
89 | printk(KERN_DEBUG "CPU%d: Thermal monitoring handled by SMI\n", | ||
90 | cpu); | ||
91 | return; /* -EBUSY */ | ||
92 | } | ||
93 | |||
94 | /* check whether a vector already exists, temporarily masked? */ | ||
95 | if (h & APIC_VECTOR_MASK) { | ||
96 | printk(KERN_DEBUG "CPU%d: Thermal LVT vector (%#x) already " | ||
97 | "installed\n", | ||
98 | cpu, (h & APIC_VECTOR_MASK)); | ||
99 | return; /* -EBUSY */ | ||
100 | } | ||
101 | |||
102 | /* The temperature transition interrupt handler setup */ | ||
103 | h = THERMAL_APIC_VECTOR; /* our delivery vector */ | ||
104 | h |= (APIC_DM_FIXED | APIC_LVT_MASKED); /* we'll mask till we're ready */ | ||
105 | apic_write(APIC_LVTTHMR, h); | ||
106 | |||
107 | rdmsr(MSR_IA32_THERM_INTERRUPT, l, h); | ||
108 | wrmsr(MSR_IA32_THERM_INTERRUPT, l | 0x03 , h); | ||
109 | |||
110 | /* ok we're good to go... */ | ||
111 | vendor_thermal_interrupt = intel_thermal_interrupt; | 71 | vendor_thermal_interrupt = intel_thermal_interrupt; |
112 | |||
113 | rdmsr(MSR_IA32_MISC_ENABLE, l, h); | ||
114 | wrmsr(MSR_IA32_MISC_ENABLE, l | MSR_IA32_MISC_ENABLE_TM1, h); | ||
115 | |||
116 | l = apic_read(APIC_LVTTHMR); | ||
117 | apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED); | ||
118 | printk(KERN_INFO "CPU%d: Thermal monitoring enabled\n", cpu); | ||
119 | |||
120 | /* enable thermal throttle processing */ | ||
121 | atomic_set(&therm_throt_en, 1); | ||
122 | return; | ||
123 | } | 72 | } |
124 | #endif /* CONFIG_X86_MCE_P4THERMAL */ | ||
125 | 73 | ||
74 | #endif /* CONFIG_X86_MCE_P4THERMAL */ | ||
126 | 75 | ||
127 | /* P4/Xeon Extended MCE MSR retrieval, return 0 if unsupported */ | 76 | /* P4/Xeon Extended MCE MSR retrieval, return 0 if unsupported */ |
128 | static inline void intel_get_extended_msrs(struct intel_mce_extended_msrs *r) | 77 | static void intel_get_extended_msrs(struct intel_mce_extended_msrs *r) |
129 | { | 78 | { |
130 | u32 h; | 79 | u32 h; |
131 | 80 | ||
@@ -143,9 +92,9 @@ static inline void intel_get_extended_msrs(struct intel_mce_extended_msrs *r) | |||
143 | 92 | ||
144 | static void intel_machine_check(struct pt_regs *regs, long error_code) | 93 | static void intel_machine_check(struct pt_regs *regs, long error_code) |
145 | { | 94 | { |
146 | int recover = 1; | ||
147 | u32 alow, ahigh, high, low; | 95 | u32 alow, ahigh, high, low; |
148 | u32 mcgstl, mcgsth; | 96 | u32 mcgstl, mcgsth; |
97 | int recover = 1; | ||
149 | int i; | 98 | int i; |
150 | 99 | ||
151 | rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth); | 100 | rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth); |
@@ -157,7 +106,9 @@ static void intel_machine_check(struct pt_regs *regs, long error_code) | |||
157 | 106 | ||
158 | if (mce_num_extended_msrs > 0) { | 107 | if (mce_num_extended_msrs > 0) { |
159 | struct intel_mce_extended_msrs dbg; | 108 | struct intel_mce_extended_msrs dbg; |
109 | |||
160 | intel_get_extended_msrs(&dbg); | 110 | intel_get_extended_msrs(&dbg); |
111 | |||
161 | printk(KERN_DEBUG "CPU %d: EIP: %08x EFLAGS: %08x\n" | 112 | printk(KERN_DEBUG "CPU %d: EIP: %08x EFLAGS: %08x\n" |
162 | "\teax: %08x ebx: %08x ecx: %08x edx: %08x\n" | 113 | "\teax: %08x ebx: %08x ecx: %08x edx: %08x\n" |
163 | "\tesi: %08x edi: %08x ebp: %08x esp: %08x\n", | 114 | "\tesi: %08x edi: %08x ebp: %08x esp: %08x\n", |
@@ -171,6 +122,7 @@ static void intel_machine_check(struct pt_regs *regs, long error_code) | |||
171 | if (high & (1<<31)) { | 122 | if (high & (1<<31)) { |
172 | char misc[20]; | 123 | char misc[20]; |
173 | char addr[24]; | 124 | char addr[24]; |
125 | |||
174 | misc[0] = addr[0] = '\0'; | 126 | misc[0] = addr[0] = '\0'; |
175 | if (high & (1<<29)) | 127 | if (high & (1<<29)) |
176 | recover |= 1; | 128 | recover |= 1; |
@@ -196,6 +148,7 @@ static void intel_machine_check(struct pt_regs *regs, long error_code) | |||
196 | panic("Unable to continue"); | 148 | panic("Unable to continue"); |
197 | 149 | ||
198 | printk(KERN_EMERG "Attempting to continue.\n"); | 150 | printk(KERN_EMERG "Attempting to continue.\n"); |
151 | |||
199 | /* | 152 | /* |
200 | * Do not clear the MSR_IA32_MCi_STATUS if the error is not | 153 | * Do not clear the MSR_IA32_MCi_STATUS if the error is not |
201 | * recoverable/continuable.This will allow BIOS to look at the MSRs | 154 | * recoverable/continuable.This will allow BIOS to look at the MSRs |
@@ -217,7 +170,6 @@ static void intel_machine_check(struct pt_regs *regs, long error_code) | |||
217 | wrmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth); | 170 | wrmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth); |
218 | } | 171 | } |
219 | 172 | ||
220 | |||
221 | void intel_p4_mcheck_init(struct cpuinfo_x86 *c) | 173 | void intel_p4_mcheck_init(struct cpuinfo_x86 *c) |
222 | { | 174 | { |
223 | u32 l, h; | 175 | u32 l, h; |
diff --git a/arch/x86/kernel/cpu/mcheck/p5.c b/arch/x86/kernel/cpu/mcheck/p5.c index c9f77ea69edc..015f481ab1b0 100644 --- a/arch/x86/kernel/cpu/mcheck/p5.c +++ b/arch/x86/kernel/cpu/mcheck/p5.c | |||
@@ -2,11 +2,10 @@ | |||
2 | * P5 specific Machine Check Exception Reporting | 2 | * P5 specific Machine Check Exception Reporting |
3 | * (C) Copyright 2002 Alan Cox <alan@lxorguk.ukuu.org.uk> | 3 | * (C) Copyright 2002 Alan Cox <alan@lxorguk.ukuu.org.uk> |
4 | */ | 4 | */ |
5 | |||
6 | #include <linux/init.h> | ||
7 | #include <linux/types.h> | ||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/interrupt.h> | 5 | #include <linux/interrupt.h> |
6 | #include <linux/kernel.h> | ||
7 | #include <linux/types.h> | ||
8 | #include <linux/init.h> | ||
10 | #include <linux/smp.h> | 9 | #include <linux/smp.h> |
11 | 10 | ||
12 | #include <asm/processor.h> | 11 | #include <asm/processor.h> |
@@ -15,39 +14,58 @@ | |||
15 | 14 | ||
16 | #include "mce.h" | 15 | #include "mce.h" |
17 | 16 | ||
18 | /* Machine check handler for Pentium class Intel */ | 17 | /* By default disabled */ |
18 | int mce_p5_enable; | ||
19 | |||
20 | /* Machine check handler for Pentium class Intel CPUs: */ | ||
19 | static void pentium_machine_check(struct pt_regs *regs, long error_code) | 21 | static void pentium_machine_check(struct pt_regs *regs, long error_code) |
20 | { | 22 | { |
21 | u32 loaddr, hi, lotype; | 23 | u32 loaddr, hi, lotype; |
24 | |||
22 | rdmsr(MSR_IA32_P5_MC_ADDR, loaddr, hi); | 25 | rdmsr(MSR_IA32_P5_MC_ADDR, loaddr, hi); |
23 | rdmsr(MSR_IA32_P5_MC_TYPE, lotype, hi); | 26 | rdmsr(MSR_IA32_P5_MC_TYPE, lotype, hi); |
24 | printk(KERN_EMERG "CPU#%d: Machine Check Exception: 0x%8X (type 0x%8X).\n", smp_processor_id(), loaddr, lotype); | 27 | |
25 | if (lotype&(1<<5)) | 28 | printk(KERN_EMERG |
26 | printk(KERN_EMERG "CPU#%d: Possible thermal failure (CPU on fire ?).\n", smp_processor_id()); | 29 | "CPU#%d: Machine Check Exception: 0x%8X (type 0x%8X).\n", |
30 | smp_processor_id(), loaddr, lotype); | ||
31 | |||
32 | if (lotype & (1<<5)) { | ||
33 | printk(KERN_EMERG | ||
34 | "CPU#%d: Possible thermal failure (CPU on fire ?).\n", | ||
35 | smp_processor_id()); | ||
36 | } | ||
37 | |||
27 | add_taint(TAINT_MACHINE_CHECK); | 38 | add_taint(TAINT_MACHINE_CHECK); |
28 | } | 39 | } |
29 | 40 | ||
30 | /* Set up machine check reporting for processors with Intel style MCE */ | 41 | /* Set up machine check reporting for processors with Intel style MCE: */ |
31 | void intel_p5_mcheck_init(struct cpuinfo_x86 *c) | 42 | void intel_p5_mcheck_init(struct cpuinfo_x86 *c) |
32 | { | 43 | { |
33 | u32 l, h; | 44 | u32 l, h; |
34 | 45 | ||
35 | /*Check for MCE support */ | 46 | /* Check for MCE support: */ |
36 | if (!cpu_has(c, X86_FEATURE_MCE)) | 47 | if (!cpu_has(c, X86_FEATURE_MCE)) |
37 | return; | 48 | return; |
38 | 49 | ||
39 | /* Default P5 to off as its often misconnected */ | 50 | #ifdef CONFIG_X86_OLD_MCE |
51 | /* Default P5 to off as its often misconnected: */ | ||
40 | if (mce_disabled != -1) | 52 | if (mce_disabled != -1) |
41 | return; | 53 | return; |
54 | #endif | ||
55 | |||
42 | machine_check_vector = pentium_machine_check; | 56 | machine_check_vector = pentium_machine_check; |
57 | /* Make sure the vector pointer is visible before we enable MCEs: */ | ||
43 | wmb(); | 58 | wmb(); |
44 | 59 | ||
45 | /* Read registers before enabling */ | 60 | /* Read registers before enabling: */ |
46 | rdmsr(MSR_IA32_P5_MC_ADDR, l, h); | 61 | rdmsr(MSR_IA32_P5_MC_ADDR, l, h); |
47 | rdmsr(MSR_IA32_P5_MC_TYPE, l, h); | 62 | rdmsr(MSR_IA32_P5_MC_TYPE, l, h); |
48 | printk(KERN_INFO "Intel old style machine check architecture supported.\n"); | 63 | printk(KERN_INFO |
64 | "Intel old style machine check architecture supported.\n"); | ||
49 | 65 | ||
50 | /* Enable MCE */ | 66 | /* Enable MCE: */ |
51 | set_in_cr4(X86_CR4_MCE); | 67 | set_in_cr4(X86_CR4_MCE); |
52 | printk(KERN_INFO "Intel old style machine check reporting enabled on CPU#%d.\n", smp_processor_id()); | 68 | printk(KERN_INFO |
69 | "Intel old style machine check reporting enabled on CPU#%d.\n", | ||
70 | smp_processor_id()); | ||
53 | } | 71 | } |
diff --git a/arch/x86/kernel/cpu/mcheck/p6.c b/arch/x86/kernel/cpu/mcheck/p6.c index 2ac52d7b434b..43c24e667457 100644 --- a/arch/x86/kernel/cpu/mcheck/p6.c +++ b/arch/x86/kernel/cpu/mcheck/p6.c | |||
@@ -2,11 +2,10 @@ | |||
2 | * P6 specific Machine Check Exception Reporting | 2 | * P6 specific Machine Check Exception Reporting |
3 | * (C) Copyright 2002 Alan Cox <alan@lxorguk.ukuu.org.uk> | 3 | * (C) Copyright 2002 Alan Cox <alan@lxorguk.ukuu.org.uk> |
4 | */ | 4 | */ |
5 | |||
6 | #include <linux/init.h> | ||
7 | #include <linux/types.h> | ||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/interrupt.h> | 5 | #include <linux/interrupt.h> |
6 | #include <linux/kernel.h> | ||
7 | #include <linux/types.h> | ||
8 | #include <linux/init.h> | ||
10 | #include <linux/smp.h> | 9 | #include <linux/smp.h> |
11 | 10 | ||
12 | #include <asm/processor.h> | 11 | #include <asm/processor.h> |
@@ -18,9 +17,9 @@ | |||
18 | /* Machine Check Handler For PII/PIII */ | 17 | /* Machine Check Handler For PII/PIII */ |
19 | static void intel_machine_check(struct pt_regs *regs, long error_code) | 18 | static void intel_machine_check(struct pt_regs *regs, long error_code) |
20 | { | 19 | { |
21 | int recover = 1; | ||
22 | u32 alow, ahigh, high, low; | 20 | u32 alow, ahigh, high, low; |
23 | u32 mcgstl, mcgsth; | 21 | u32 mcgstl, mcgsth; |
22 | int recover = 1; | ||
24 | int i; | 23 | int i; |
25 | 24 | ||
26 | rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth); | 25 | rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth); |
@@ -35,12 +34,16 @@ static void intel_machine_check(struct pt_regs *regs, long error_code) | |||
35 | if (high & (1<<31)) { | 34 | if (high & (1<<31)) { |
36 | char misc[20]; | 35 | char misc[20]; |
37 | char addr[24]; | 36 | char addr[24]; |
38 | misc[0] = addr[0] = '\0'; | 37 | |
38 | misc[0] = '\0'; | ||
39 | addr[0] = '\0'; | ||
40 | |||
39 | if (high & (1<<29)) | 41 | if (high & (1<<29)) |
40 | recover |= 1; | 42 | recover |= 1; |
41 | if (high & (1<<25)) | 43 | if (high & (1<<25)) |
42 | recover |= 2; | 44 | recover |= 2; |
43 | high &= ~(1<<31); | 45 | high &= ~(1<<31); |
46 | |||
44 | if (high & (1<<27)) { | 47 | if (high & (1<<27)) { |
45 | rdmsr(MSR_IA32_MC0_MISC+i*4, alow, ahigh); | 48 | rdmsr(MSR_IA32_MC0_MISC+i*4, alow, ahigh); |
46 | snprintf(misc, 20, "[%08x%08x]", ahigh, alow); | 49 | snprintf(misc, 20, "[%08x%08x]", ahigh, alow); |
@@ -49,6 +52,7 @@ static void intel_machine_check(struct pt_regs *regs, long error_code) | |||
49 | rdmsr(MSR_IA32_MC0_ADDR+i*4, alow, ahigh); | 52 | rdmsr(MSR_IA32_MC0_ADDR+i*4, alow, ahigh); |
50 | snprintf(addr, 24, " at %08x%08x", ahigh, alow); | 53 | snprintf(addr, 24, " at %08x%08x", ahigh, alow); |
51 | } | 54 | } |
55 | |||
52 | printk(KERN_EMERG "CPU %d: Bank %d: %08x%08x%s%s\n", | 56 | printk(KERN_EMERG "CPU %d: Bank %d: %08x%08x%s%s\n", |
53 | smp_processor_id(), i, high, low, misc, addr); | 57 | smp_processor_id(), i, high, low, misc, addr); |
54 | } | 58 | } |
@@ -63,16 +67,17 @@ static void intel_machine_check(struct pt_regs *regs, long error_code) | |||
63 | /* | 67 | /* |
64 | * Do not clear the MSR_IA32_MCi_STATUS if the error is not | 68 | * Do not clear the MSR_IA32_MCi_STATUS if the error is not |
65 | * recoverable/continuable.This will allow BIOS to look at the MSRs | 69 | * recoverable/continuable.This will allow BIOS to look at the MSRs |
66 | * for errors if the OS could not log the error. | 70 | * for errors if the OS could not log the error: |
67 | */ | 71 | */ |
68 | for (i = 0; i < nr_mce_banks; i++) { | 72 | for (i = 0; i < nr_mce_banks; i++) { |
69 | unsigned int msr; | 73 | unsigned int msr; |
74 | |||
70 | msr = MSR_IA32_MC0_STATUS+i*4; | 75 | msr = MSR_IA32_MC0_STATUS+i*4; |
71 | rdmsr(msr, low, high); | 76 | rdmsr(msr, low, high); |
72 | if (high & (1<<31)) { | 77 | if (high & (1<<31)) { |
73 | /* Clear it */ | 78 | /* Clear it: */ |
74 | wrmsr(msr, 0UL, 0UL); | 79 | wrmsr(msr, 0UL, 0UL); |
75 | /* Serialize */ | 80 | /* Serialize: */ |
76 | wmb(); | 81 | wmb(); |
77 | add_taint(TAINT_MACHINE_CHECK); | 82 | add_taint(TAINT_MACHINE_CHECK); |
78 | } | 83 | } |
@@ -81,7 +86,7 @@ static void intel_machine_check(struct pt_regs *regs, long error_code) | |||
81 | wrmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth); | 86 | wrmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth); |
82 | } | 87 | } |
83 | 88 | ||
84 | /* Set up machine check reporting for processors with Intel style MCE */ | 89 | /* Set up machine check reporting for processors with Intel style MCE: */ |
85 | void intel_p6_mcheck_init(struct cpuinfo_x86 *c) | 90 | void intel_p6_mcheck_init(struct cpuinfo_x86 *c) |
86 | { | 91 | { |
87 | u32 l, h; | 92 | u32 l, h; |
@@ -97,6 +102,7 @@ void intel_p6_mcheck_init(struct cpuinfo_x86 *c) | |||
97 | 102 | ||
98 | /* Ok machine check is available */ | 103 | /* Ok machine check is available */ |
99 | machine_check_vector = intel_machine_check; | 104 | machine_check_vector = intel_machine_check; |
105 | /* Make sure the vector pointer is visible before we enable MCEs: */ | ||
100 | wmb(); | 106 | wmb(); |
101 | 107 | ||
102 | printk(KERN_INFO "Intel machine check architecture supported.\n"); | 108 | printk(KERN_INFO "Intel machine check architecture supported.\n"); |
diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c index d5ae2243f0b9..7b1ae2e20ba5 100644 --- a/arch/x86/kernel/cpu/mcheck/therm_throt.c +++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * | ||
3 | * Thermal throttle event support code (such as syslog messaging and rate | 2 | * Thermal throttle event support code (such as syslog messaging and rate |
4 | * limiting) that was factored out from x86_64 (mce_intel.c) and i386 (p4.c). | 3 | * limiting) that was factored out from x86_64 (mce_intel.c) and i386 (p4.c). |
4 | * | ||
5 | * This allows consistent reporting of CPU thermal throttle events. | 5 | * This allows consistent reporting of CPU thermal throttle events. |
6 | * | 6 | * |
7 | * Maintains a counter in /sys that keeps track of the number of thermal | 7 | * Maintains a counter in /sys that keeps track of the number of thermal |
@@ -13,43 +13,43 @@ | |||
13 | * Credits: Adapted from Zwane Mwaikambo's original code in mce_intel.c. | 13 | * Credits: Adapted from Zwane Mwaikambo's original code in mce_intel.c. |
14 | * Inspired by Ross Biro's and Al Borchers' counter code. | 14 | * Inspired by Ross Biro's and Al Borchers' counter code. |
15 | */ | 15 | */ |
16 | 16 | #include <linux/notifier.h> | |
17 | #include <linux/jiffies.h> | ||
17 | #include <linux/percpu.h> | 18 | #include <linux/percpu.h> |
18 | #include <linux/sysdev.h> | 19 | #include <linux/sysdev.h> |
19 | #include <linux/cpu.h> | 20 | #include <linux/cpu.h> |
20 | #include <asm/cpu.h> | 21 | |
21 | #include <linux/notifier.h> | ||
22 | #include <linux/jiffies.h> | ||
23 | #include <asm/therm_throt.h> | 22 | #include <asm/therm_throt.h> |
24 | 23 | ||
25 | /* How long to wait between reporting thermal events */ | 24 | /* How long to wait between reporting thermal events */ |
26 | #define CHECK_INTERVAL (300 * HZ) | 25 | #define CHECK_INTERVAL (300 * HZ) |
27 | 26 | ||
28 | static DEFINE_PER_CPU(__u64, next_check) = INITIAL_JIFFIES; | 27 | static DEFINE_PER_CPU(__u64, next_check) = INITIAL_JIFFIES; |
29 | static DEFINE_PER_CPU(unsigned long, thermal_throttle_count); | 28 | static DEFINE_PER_CPU(unsigned long, thermal_throttle_count); |
30 | atomic_t therm_throt_en = ATOMIC_INIT(0); | 29 | |
30 | atomic_t therm_throt_en = ATOMIC_INIT(0); | ||
31 | 31 | ||
32 | #ifdef CONFIG_SYSFS | 32 | #ifdef CONFIG_SYSFS |
33 | #define define_therm_throt_sysdev_one_ro(_name) \ | 33 | #define define_therm_throt_sysdev_one_ro(_name) \ |
34 | static SYSDEV_ATTR(_name, 0444, therm_throt_sysdev_show_##_name, NULL) | 34 | static SYSDEV_ATTR(_name, 0444, therm_throt_sysdev_show_##_name, NULL) |
35 | 35 | ||
36 | #define define_therm_throt_sysdev_show_func(name) \ | 36 | #define define_therm_throt_sysdev_show_func(name) \ |
37 | static ssize_t therm_throt_sysdev_show_##name(struct sys_device *dev, \ | 37 | static ssize_t therm_throt_sysdev_show_##name(struct sys_device *dev, \ |
38 | struct sysdev_attribute *attr, \ | 38 | struct sysdev_attribute *attr, \ |
39 | char *buf) \ | 39 | char *buf) \ |
40 | { \ | 40 | { \ |
41 | unsigned int cpu = dev->id; \ | 41 | unsigned int cpu = dev->id; \ |
42 | ssize_t ret; \ | 42 | ssize_t ret; \ |
43 | \ | 43 | \ |
44 | preempt_disable(); /* CPU hotplug */ \ | 44 | preempt_disable(); /* CPU hotplug */ \ |
45 | if (cpu_online(cpu)) \ | 45 | if (cpu_online(cpu)) \ |
46 | ret = sprintf(buf, "%lu\n", \ | 46 | ret = sprintf(buf, "%lu\n", \ |
47 | per_cpu(thermal_throttle_##name, cpu)); \ | 47 | per_cpu(thermal_throttle_##name, cpu)); \ |
48 | else \ | 48 | else \ |
49 | ret = 0; \ | 49 | ret = 0; \ |
50 | preempt_enable(); \ | 50 | preempt_enable(); \ |
51 | \ | 51 | \ |
52 | return ret; \ | 52 | return ret; \ |
53 | } | 53 | } |
54 | 54 | ||
55 | define_therm_throt_sysdev_show_func(count); | 55 | define_therm_throt_sysdev_show_func(count); |
@@ -61,8 +61,8 @@ static struct attribute *thermal_throttle_attrs[] = { | |||
61 | }; | 61 | }; |
62 | 62 | ||
63 | static struct attribute_group thermal_throttle_attr_group = { | 63 | static struct attribute_group thermal_throttle_attr_group = { |
64 | .attrs = thermal_throttle_attrs, | 64 | .attrs = thermal_throttle_attrs, |
65 | .name = "thermal_throttle" | 65 | .name = "thermal_throttle" |
66 | }; | 66 | }; |
67 | #endif /* CONFIG_SYSFS */ | 67 | #endif /* CONFIG_SYSFS */ |
68 | 68 | ||
@@ -110,10 +110,11 @@ int therm_throt_process(int curr) | |||
110 | } | 110 | } |
111 | 111 | ||
112 | #ifdef CONFIG_SYSFS | 112 | #ifdef CONFIG_SYSFS |
113 | /* Add/Remove thermal_throttle interface for CPU device */ | 113 | /* Add/Remove thermal_throttle interface for CPU device: */ |
114 | static __cpuinit int thermal_throttle_add_dev(struct sys_device *sys_dev) | 114 | static __cpuinit int thermal_throttle_add_dev(struct sys_device *sys_dev) |
115 | { | 115 | { |
116 | return sysfs_create_group(&sys_dev->kobj, &thermal_throttle_attr_group); | 116 | return sysfs_create_group(&sys_dev->kobj, |
117 | &thermal_throttle_attr_group); | ||
117 | } | 118 | } |
118 | 119 | ||
119 | static __cpuinit void thermal_throttle_remove_dev(struct sys_device *sys_dev) | 120 | static __cpuinit void thermal_throttle_remove_dev(struct sys_device *sys_dev) |
@@ -121,19 +122,21 @@ static __cpuinit void thermal_throttle_remove_dev(struct sys_device *sys_dev) | |||
121 | sysfs_remove_group(&sys_dev->kobj, &thermal_throttle_attr_group); | 122 | sysfs_remove_group(&sys_dev->kobj, &thermal_throttle_attr_group); |
122 | } | 123 | } |
123 | 124 | ||
124 | /* Mutex protecting device creation against CPU hotplug */ | 125 | /* Mutex protecting device creation against CPU hotplug: */ |
125 | static DEFINE_MUTEX(therm_cpu_lock); | 126 | static DEFINE_MUTEX(therm_cpu_lock); |
126 | 127 | ||
127 | /* Get notified when a cpu comes on/off. Be hotplug friendly. */ | 128 | /* Get notified when a cpu comes on/off. Be hotplug friendly. */ |
128 | static __cpuinit int thermal_throttle_cpu_callback(struct notifier_block *nfb, | 129 | static __cpuinit int |
129 | unsigned long action, | 130 | thermal_throttle_cpu_callback(struct notifier_block *nfb, |
130 | void *hcpu) | 131 | unsigned long action, |
132 | void *hcpu) | ||
131 | { | 133 | { |
132 | unsigned int cpu = (unsigned long)hcpu; | 134 | unsigned int cpu = (unsigned long)hcpu; |
133 | struct sys_device *sys_dev; | 135 | struct sys_device *sys_dev; |
134 | int err = 0; | 136 | int err = 0; |
135 | 137 | ||
136 | sys_dev = get_cpu_sysdev(cpu); | 138 | sys_dev = get_cpu_sysdev(cpu); |
139 | |||
137 | switch (action) { | 140 | switch (action) { |
138 | case CPU_UP_PREPARE: | 141 | case CPU_UP_PREPARE: |
139 | case CPU_UP_PREPARE_FROZEN: | 142 | case CPU_UP_PREPARE_FROZEN: |
diff --git a/arch/x86/kernel/cpu/mcheck/threshold.c b/arch/x86/kernel/cpu/mcheck/threshold.c index 23ee9e730f78..d746df2909c9 100644 --- a/arch/x86/kernel/cpu/mcheck/threshold.c +++ b/arch/x86/kernel/cpu/mcheck/threshold.c | |||
@@ -17,7 +17,7 @@ static void default_threshold_interrupt(void) | |||
17 | 17 | ||
18 | void (*mce_threshold_vector)(void) = default_threshold_interrupt; | 18 | void (*mce_threshold_vector)(void) = default_threshold_interrupt; |
19 | 19 | ||
20 | asmlinkage void mce_threshold_interrupt(void) | 20 | asmlinkage void smp_threshold_interrupt(void) |
21 | { | 21 | { |
22 | exit_idle(); | 22 | exit_idle(); |
23 | irq_enter(); | 23 | irq_enter(); |
diff --git a/arch/x86/kernel/cpu/mcheck/winchip.c b/arch/x86/kernel/cpu/mcheck/winchip.c index 2a043d89811d..81b02487090b 100644 --- a/arch/x86/kernel/cpu/mcheck/winchip.c +++ b/arch/x86/kernel/cpu/mcheck/winchip.c | |||
@@ -2,11 +2,10 @@ | |||
2 | * IDT Winchip specific Machine Check Exception Reporting | 2 | * IDT Winchip specific Machine Check Exception Reporting |
3 | * (C) Copyright 2002 Alan Cox <alan@lxorguk.ukuu.org.uk> | 3 | * (C) Copyright 2002 Alan Cox <alan@lxorguk.ukuu.org.uk> |
4 | */ | 4 | */ |
5 | |||
6 | #include <linux/init.h> | ||
7 | #include <linux/types.h> | ||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/interrupt.h> | 5 | #include <linux/interrupt.h> |
6 | #include <linux/kernel.h> | ||
7 | #include <linux/types.h> | ||
8 | #include <linux/init.h> | ||
10 | 9 | ||
11 | #include <asm/processor.h> | 10 | #include <asm/processor.h> |
12 | #include <asm/system.h> | 11 | #include <asm/system.h> |
@@ -14,7 +13,7 @@ | |||
14 | 13 | ||
15 | #include "mce.h" | 14 | #include "mce.h" |
16 | 15 | ||
17 | /* Machine check handler for WinChip C6 */ | 16 | /* Machine check handler for WinChip C6: */ |
18 | static void winchip_machine_check(struct pt_regs *regs, long error_code) | 17 | static void winchip_machine_check(struct pt_regs *regs, long error_code) |
19 | { | 18 | { |
20 | printk(KERN_EMERG "CPU0: Machine Check Exception.\n"); | 19 | printk(KERN_EMERG "CPU0: Machine Check Exception.\n"); |
@@ -25,12 +24,18 @@ static void winchip_machine_check(struct pt_regs *regs, long error_code) | |||
25 | void winchip_mcheck_init(struct cpuinfo_x86 *c) | 24 | void winchip_mcheck_init(struct cpuinfo_x86 *c) |
26 | { | 25 | { |
27 | u32 lo, hi; | 26 | u32 lo, hi; |
27 | |||
28 | machine_check_vector = winchip_machine_check; | 28 | machine_check_vector = winchip_machine_check; |
29 | /* Make sure the vector pointer is visible before we enable MCEs: */ | ||
29 | wmb(); | 30 | wmb(); |
31 | |||
30 | rdmsr(MSR_IDT_FCR1, lo, hi); | 32 | rdmsr(MSR_IDT_FCR1, lo, hi); |
31 | lo |= (1<<2); /* Enable EIERRINT (int 18 MCE) */ | 33 | lo |= (1<<2); /* Enable EIERRINT (int 18 MCE) */ |
32 | lo &= ~(1<<4); /* Enable MCE */ | 34 | lo &= ~(1<<4); /* Enable MCE */ |
33 | wrmsr(MSR_IDT_FCR1, lo, hi); | 35 | wrmsr(MSR_IDT_FCR1, lo, hi); |
36 | |||
34 | set_in_cr4(X86_CR4_MCE); | 37 | set_in_cr4(X86_CR4_MCE); |
35 | printk(KERN_INFO "Winchip machine check reporting enabled on CPU#0.\n"); | 38 | |
39 | printk(KERN_INFO | ||
40 | "Winchip machine check reporting enabled on CPU#0.\n"); | ||
36 | } | 41 | } |
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index a4742a340d8d..de74f0a3e0ed 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
@@ -963,6 +963,8 @@ END(\sym) | |||
963 | #ifdef CONFIG_SMP | 963 | #ifdef CONFIG_SMP |
964 | apicinterrupt IRQ_MOVE_CLEANUP_VECTOR \ | 964 | apicinterrupt IRQ_MOVE_CLEANUP_VECTOR \ |
965 | irq_move_cleanup_interrupt smp_irq_move_cleanup_interrupt | 965 | irq_move_cleanup_interrupt smp_irq_move_cleanup_interrupt |
966 | apicinterrupt REBOOT_VECTOR \ | ||
967 | reboot_interrupt smp_reboot_interrupt | ||
966 | #endif | 968 | #endif |
967 | 969 | ||
968 | #ifdef CONFIG_X86_UV | 970 | #ifdef CONFIG_X86_UV |
@@ -994,10 +996,15 @@ apicinterrupt INVALIDATE_TLB_VECTOR_START+7 \ | |||
994 | #endif | 996 | #endif |
995 | 997 | ||
996 | apicinterrupt THRESHOLD_APIC_VECTOR \ | 998 | apicinterrupt THRESHOLD_APIC_VECTOR \ |
997 | threshold_interrupt mce_threshold_interrupt | 999 | threshold_interrupt smp_threshold_interrupt |
998 | apicinterrupt THERMAL_APIC_VECTOR \ | 1000 | apicinterrupt THERMAL_APIC_VECTOR \ |
999 | thermal_interrupt smp_thermal_interrupt | 1001 | thermal_interrupt smp_thermal_interrupt |
1000 | 1002 | ||
1003 | #ifdef CONFIG_X86_MCE | ||
1004 | apicinterrupt MCE_SELF_VECTOR \ | ||
1005 | mce_self_interrupt smp_mce_self_interrupt | ||
1006 | #endif | ||
1007 | |||
1001 | #ifdef CONFIG_SMP | 1008 | #ifdef CONFIG_SMP |
1002 | apicinterrupt CALL_FUNCTION_SINGLE_VECTOR \ | 1009 | apicinterrupt CALL_FUNCTION_SINGLE_VECTOR \ |
1003 | call_function_single_interrupt smp_call_function_single_interrupt | 1010 | call_function_single_interrupt smp_call_function_single_interrupt |
@@ -1379,7 +1386,7 @@ errorentry xen_stack_segment do_stack_segment | |||
1379 | errorentry general_protection do_general_protection | 1386 | errorentry general_protection do_general_protection |
1380 | errorentry page_fault do_page_fault | 1387 | errorentry page_fault do_page_fault |
1381 | #ifdef CONFIG_X86_MCE | 1388 | #ifdef CONFIG_X86_MCE |
1382 | paranoidzeroentry machine_check do_machine_check | 1389 | paranoidzeroentry machine_check *machine_check_vector(%rip) |
1383 | #endif | 1390 | #endif |
1384 | 1391 | ||
1385 | /* | 1392 | /* |
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index 38287b5f116e..b0cdde6932f5 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <asm/io_apic.h> | 12 | #include <asm/io_apic.h> |
13 | #include <asm/irq.h> | 13 | #include <asm/irq.h> |
14 | #include <asm/idle.h> | 14 | #include <asm/idle.h> |
15 | #include <asm/mce.h> | ||
15 | #include <asm/hw_irq.h> | 16 | #include <asm/hw_irq.h> |
16 | 17 | ||
17 | atomic_t irq_err_count; | 18 | atomic_t irq_err_count; |
@@ -96,13 +97,23 @@ static int show_other_interrupts(struct seq_file *p, int prec) | |||
96 | for_each_online_cpu(j) | 97 | for_each_online_cpu(j) |
97 | seq_printf(p, "%10u ", irq_stats(j)->irq_thermal_count); | 98 | seq_printf(p, "%10u ", irq_stats(j)->irq_thermal_count); |
98 | seq_printf(p, " Thermal event interrupts\n"); | 99 | seq_printf(p, " Thermal event interrupts\n"); |
99 | # ifdef CONFIG_X86_64 | 100 | # ifdef CONFIG_X86_MCE_THRESHOLD |
100 | seq_printf(p, "%*s: ", prec, "THR"); | 101 | seq_printf(p, "%*s: ", prec, "THR"); |
101 | for_each_online_cpu(j) | 102 | for_each_online_cpu(j) |
102 | seq_printf(p, "%10u ", irq_stats(j)->irq_threshold_count); | 103 | seq_printf(p, "%10u ", irq_stats(j)->irq_threshold_count); |
103 | seq_printf(p, " Threshold APIC interrupts\n"); | 104 | seq_printf(p, " Threshold APIC interrupts\n"); |
104 | # endif | 105 | # endif |
105 | #endif | 106 | #endif |
107 | #ifdef CONFIG_X86_NEW_MCE | ||
108 | seq_printf(p, "%*s: ", prec, "MCE"); | ||
109 | for_each_online_cpu(j) | ||
110 | seq_printf(p, "%10u ", per_cpu(mce_exception_count, j)); | ||
111 | seq_printf(p, " Machine check exceptions\n"); | ||
112 | seq_printf(p, "%*s: ", prec, "MCP"); | ||
113 | for_each_online_cpu(j) | ||
114 | seq_printf(p, "%10u ", per_cpu(mce_poll_count, j)); | ||
115 | seq_printf(p, " Machine check polls\n"); | ||
116 | #endif | ||
106 | seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count)); | 117 | seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count)); |
107 | #if defined(CONFIG_X86_IO_APIC) | 118 | #if defined(CONFIG_X86_IO_APIC) |
108 | seq_printf(p, "%*s: %10u\n", prec, "MIS", atomic_read(&irq_mis_count)); | 119 | seq_printf(p, "%*s: %10u\n", prec, "MIS", atomic_read(&irq_mis_count)); |
@@ -185,10 +196,14 @@ u64 arch_irq_stat_cpu(unsigned int cpu) | |||
185 | #endif | 196 | #endif |
186 | #ifdef CONFIG_X86_MCE | 197 | #ifdef CONFIG_X86_MCE |
187 | sum += irq_stats(cpu)->irq_thermal_count; | 198 | sum += irq_stats(cpu)->irq_thermal_count; |
188 | # ifdef CONFIG_X86_64 | 199 | # ifdef CONFIG_X86_MCE_THRESHOLD |
189 | sum += irq_stats(cpu)->irq_threshold_count; | 200 | sum += irq_stats(cpu)->irq_threshold_count; |
190 | # endif | 201 | # endif |
191 | #endif | 202 | #endif |
203 | #ifdef CONFIG_X86_NEW_MCE | ||
204 | sum += per_cpu(mce_exception_count, cpu); | ||
205 | sum += per_cpu(mce_poll_count, cpu); | ||
206 | #endif | ||
192 | return sum; | 207 | return sum; |
193 | } | 208 | } |
194 | 209 | ||
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c index 267c6624c77f..696f0e475c2d 100644 --- a/arch/x86/kernel/irqinit.c +++ b/arch/x86/kernel/irqinit.c | |||
@@ -173,6 +173,9 @@ static void __init smp_intr_init(void) | |||
173 | /* Low priority IPI to cleanup after moving an irq */ | 173 | /* Low priority IPI to cleanup after moving an irq */ |
174 | set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt); | 174 | set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt); |
175 | set_bit(IRQ_MOVE_CLEANUP_VECTOR, used_vectors); | 175 | set_bit(IRQ_MOVE_CLEANUP_VECTOR, used_vectors); |
176 | |||
177 | /* IPI used for rebooting/stopping */ | ||
178 | alloc_intr_gate(REBOOT_VECTOR, reboot_interrupt); | ||
176 | #endif | 179 | #endif |
177 | #endif /* CONFIG_SMP */ | 180 | #endif /* CONFIG_SMP */ |
178 | } | 181 | } |
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index 0a813b17b172..4c578751e94e 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c | |||
@@ -24,11 +24,11 @@ | |||
24 | #include <asm/ucontext.h> | 24 | #include <asm/ucontext.h> |
25 | #include <asm/i387.h> | 25 | #include <asm/i387.h> |
26 | #include <asm/vdso.h> | 26 | #include <asm/vdso.h> |
27 | #include <asm/mce.h> | ||
27 | 28 | ||
28 | #ifdef CONFIG_X86_64 | 29 | #ifdef CONFIG_X86_64 |
29 | #include <asm/proto.h> | 30 | #include <asm/proto.h> |
30 | #include <asm/ia32_unistd.h> | 31 | #include <asm/ia32_unistd.h> |
31 | #include <asm/mce.h> | ||
32 | #endif /* CONFIG_X86_64 */ | 32 | #endif /* CONFIG_X86_64 */ |
33 | 33 | ||
34 | #include <asm/syscall.h> | 34 | #include <asm/syscall.h> |
@@ -856,10 +856,10 @@ static void do_signal(struct pt_regs *regs) | |||
856 | void | 856 | void |
857 | do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) | 857 | do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) |
858 | { | 858 | { |
859 | #if defined(CONFIG_X86_64) && defined(CONFIG_X86_MCE) | 859 | #ifdef CONFIG_X86_NEW_MCE |
860 | /* notify userspace of pending MCEs */ | 860 | /* notify userspace of pending MCEs */ |
861 | if (thread_info_flags & _TIF_MCE_NOTIFY) | 861 | if (thread_info_flags & _TIF_MCE_NOTIFY) |
862 | mce_notify_user(); | 862 | mce_notify_process(); |
863 | #endif /* CONFIG_X86_64 && CONFIG_X86_MCE */ | 863 | #endif /* CONFIG_X86_64 && CONFIG_X86_MCE */ |
864 | 864 | ||
865 | /* deal with pending signal delivery */ | 865 | /* deal with pending signal delivery */ |
diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c index 28f5fb495a66..ec1de97600e7 100644 --- a/arch/x86/kernel/smp.c +++ b/arch/x86/kernel/smp.c | |||
@@ -150,14 +150,40 @@ void native_send_call_func_ipi(const struct cpumask *mask) | |||
150 | * this function calls the 'stop' function on all other CPUs in the system. | 150 | * this function calls the 'stop' function on all other CPUs in the system. |
151 | */ | 151 | */ |
152 | 152 | ||
153 | asmlinkage void smp_reboot_interrupt(void) | ||
154 | { | ||
155 | ack_APIC_irq(); | ||
156 | irq_enter(); | ||
157 | stop_this_cpu(NULL); | ||
158 | irq_exit(); | ||
159 | } | ||
160 | |||
153 | static void native_smp_send_stop(void) | 161 | static void native_smp_send_stop(void) |
154 | { | 162 | { |
155 | unsigned long flags; | 163 | unsigned long flags; |
164 | unsigned long wait; | ||
156 | 165 | ||
157 | if (reboot_force) | 166 | if (reboot_force) |
158 | return; | 167 | return; |
159 | 168 | ||
160 | smp_call_function(stop_this_cpu, NULL, 0); | 169 | /* |
170 | * Use an own vector here because smp_call_function | ||
171 | * does lots of things not suitable in a panic situation. | ||
172 | * On most systems we could also use an NMI here, | ||
173 | * but there are a few systems around where NMI | ||
174 | * is problematic so stay with an non NMI for now | ||
175 | * (this implies we cannot stop CPUs spinning with irq off | ||
176 | * currently) | ||
177 | */ | ||
178 | if (num_online_cpus() > 1) { | ||
179 | apic->send_IPI_allbutself(REBOOT_VECTOR); | ||
180 | |||
181 | /* Don't wait longer than a second */ | ||
182 | wait = USEC_PER_SEC; | ||
183 | while (num_online_cpus() > 1 && wait--) | ||
184 | udelay(1); | ||
185 | } | ||
186 | |||
161 | local_irq_save(flags); | 187 | local_irq_save(flags); |
162 | disable_local_APIC(); | 188 | disable_local_APIC(); |
163 | local_irq_restore(flags); | 189 | local_irq_restore(flags); |
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 07d60c870ce2..1e1e27b7d438 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c | |||
@@ -798,15 +798,15 @@ unsigned long patch_espfix_desc(unsigned long uesp, unsigned long kesp) | |||
798 | 798 | ||
799 | return new_kesp; | 799 | return new_kesp; |
800 | } | 800 | } |
801 | #else | 801 | #endif |
802 | |||
802 | asmlinkage void __attribute__((weak)) smp_thermal_interrupt(void) | 803 | asmlinkage void __attribute__((weak)) smp_thermal_interrupt(void) |
803 | { | 804 | { |
804 | } | 805 | } |
805 | 806 | ||
806 | asmlinkage void __attribute__((weak)) mce_threshold_interrupt(void) | 807 | asmlinkage void __attribute__((weak)) smp_threshold_interrupt(void) |
807 | { | 808 | { |
808 | } | 809 | } |
809 | #endif | ||
810 | 810 | ||
811 | /* | 811 | /* |
812 | * 'math_state_restore()' saves the current math information in the | 812 | * 'math_state_restore()' saves the current math information in the |