mce.c (0a182611d149b5b747014fbb230ec35b20a45c86) | mce.c (cc15ff3275694fedc33cd3d53212a43eec7aa0bc) |
---|---|
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Machine check exception handling. 4 * 5 * Copyright 2013 IBM Corporation 6 * Author: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com> 7 */ 8 --- 14 unchanged lines hidden (view full) --- 23#include <asm/interrupt.h> 24#include <asm/machdep.h> 25#include <asm/mce.h> 26#include <asm/nmi.h> 27#include <asm/asm-prototypes.h> 28 29#include "setup.h" 30 | 1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Machine check exception handling. 4 * 5 * Copyright 2013 IBM Corporation 6 * Author: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com> 7 */ 8 --- 14 unchanged lines hidden (view full) --- 23#include <asm/interrupt.h> 24#include <asm/machdep.h> 25#include <asm/mce.h> 26#include <asm/nmi.h> 27#include <asm/asm-prototypes.h> 28 29#include "setup.h" 30 |
31static void machine_check_process_queued_event(struct irq_work *work); 32static void machine_check_ue_irq_work(struct irq_work *work); | |
33static void machine_check_ue_event(struct machine_check_event *evt); 34static void machine_process_ue_event(struct work_struct *work); 35 | 31static void machine_check_ue_event(struct machine_check_event *evt); 32static void machine_process_ue_event(struct work_struct *work); 33 |
36static struct irq_work mce_event_process_work = { 37 .func = machine_check_process_queued_event, 38}; 39 40static struct irq_work mce_ue_event_irq_work = { 41 .func = machine_check_ue_irq_work, 42}; 43 | |
44static DECLARE_WORK(mce_ue_event_work, machine_process_ue_event); 45 46static BLOCKING_NOTIFIER_HEAD(mce_notifier_list); 47 48int mce_register_notifier(struct notifier_block *nb) 49{ 50 return blocking_notifier_chain_register(&mce_notifier_list, nb); 51} --- 32 unchanged lines hidden (view full) --- 84 mce->u.link_error.link_error_type = mce_err->u.link_error_type; 85 break; 86 case MCE_ERROR_TYPE_UNKNOWN: 87 default: 88 break; 89 } 90} 91 | 34static DECLARE_WORK(mce_ue_event_work, machine_process_ue_event); 35 36static BLOCKING_NOTIFIER_HEAD(mce_notifier_list); 37 38int mce_register_notifier(struct notifier_block *nb) 39{ 40 return blocking_notifier_chain_register(&mce_notifier_list, nb); 41} --- 32 unchanged lines hidden (view full) --- 74 mce->u.link_error.link_error_type = mce_err->u.link_error_type; 75 break; 76 case MCE_ERROR_TYPE_UNKNOWN: 77 default: 78 break; 79 } 80} 81 |
82void mce_irq_work_queue(void) 83{ 84 /* Raise decrementer interrupt */ 85 arch_irq_work_raise(); 86 set_mce_pending_irq_work(); 87} 88 |
|
92/* 93 * Decode and save high level MCE information into per cpu buffer which 94 * is an array of machine_check_event structure. 95 */ 96void save_mce_event(struct pt_regs *regs, long handled, 97 struct mce_error_info *mce_err, 98 uint64_t nip, uint64_t addr, uint64_t phys_addr) 99{ --- 112 unchanged lines hidden (view full) --- 212 return ret; 213} 214 215void release_mce_event(void) 216{ 217 get_mce_event(NULL, true); 218} 219 | 89/* 90 * Decode and save high level MCE information into per cpu buffer which 91 * is an array of machine_check_event structure. 92 */ 93void save_mce_event(struct pt_regs *regs, long handled, 94 struct mce_error_info *mce_err, 95 uint64_t nip, uint64_t addr, uint64_t phys_addr) 96{ --- 112 unchanged lines hidden (view full) --- 209 return ret; 210} 211 212void release_mce_event(void) 213{ 214 get_mce_event(NULL, true); 215} 216 |
220static void machine_check_ue_irq_work(struct irq_work *work) | 217static void machine_check_ue_work(void) |
221{ 222 schedule_work(&mce_ue_event_work); 223} 224 225/* 226 * Queue up the MCE event which then can be handled later. 227 */ 228static void machine_check_ue_event(struct machine_check_event *evt) --- 5 unchanged lines hidden (view full) --- 234 if (index >= MAX_MC_EVT) { 235 local_paca->mce_info->mce_ue_count--; 236 return; 237 } 238 memcpy(&local_paca->mce_info->mce_ue_event_queue[index], 239 evt, sizeof(*evt)); 240 241 /* Queue work to process this event later. */ | 218{ 219 schedule_work(&mce_ue_event_work); 220} 221 222/* 223 * Queue up the MCE event which then can be handled later. 224 */ 225static void machine_check_ue_event(struct machine_check_event *evt) --- 5 unchanged lines hidden (view full) --- 231 if (index >= MAX_MC_EVT) { 232 local_paca->mce_info->mce_ue_count--; 233 return; 234 } 235 memcpy(&local_paca->mce_info->mce_ue_event_queue[index], 236 evt, sizeof(*evt)); 237 238 /* Queue work to process this event later. */ |
242 irq_work_queue(&mce_ue_event_irq_work); | 239 mce_irq_work_queue(); |
243} 244 245/* 246 * Queue up the MCE event which then can be handled later. 247 */ 248void machine_check_queue_event(void) 249{ 250 int index; 251 struct machine_check_event evt; | 240} 241 242/* 243 * Queue up the MCE event which then can be handled later. 244 */ 245void machine_check_queue_event(void) 246{ 247 int index; 248 struct machine_check_event evt; |
252 unsigned long msr; | |
253 254 if (!get_mce_event(&evt, MCE_EVENT_RELEASE)) 255 return; 256 257 index = local_paca->mce_info->mce_queue_count++; 258 /* If queue is full, just return for now. */ 259 if (index >= MAX_MC_EVT) { 260 local_paca->mce_info->mce_queue_count--; 261 return; 262 } 263 memcpy(&local_paca->mce_info->mce_event_queue[index], 264 &evt, sizeof(evt)); 265 | 249 250 if (!get_mce_event(&evt, MCE_EVENT_RELEASE)) 251 return; 252 253 index = local_paca->mce_info->mce_queue_count++; 254 /* If queue is full, just return for now. */ 255 if (index >= MAX_MC_EVT) { 256 local_paca->mce_info->mce_queue_count--; 257 return; 258 } 259 memcpy(&local_paca->mce_info->mce_event_queue[index], 260 &evt, sizeof(evt)); 261 |
266 /* 267 * Queue irq work to process this event later. Before 268 * queuing the work enable translation for non radix LPAR, 269 * as irq_work_queue may try to access memory outside RMO 270 * region. 271 */ 272 if (!radix_enabled() && firmware_has_feature(FW_FEATURE_LPAR)) { 273 msr = mfmsr(); 274 mtmsr(msr | MSR_IR | MSR_DR); 275 irq_work_queue(&mce_event_process_work); 276 mtmsr(msr); 277 } else { 278 irq_work_queue(&mce_event_process_work); 279 } | 262 mce_irq_work_queue(); |
280} 281 282void mce_common_process_ue(struct pt_regs *regs, 283 struct mce_error_info *mce_err) 284{ 285 const struct exception_table_entry *entry; 286 287 entry = search_kernel_exception_table(regs->nip); --- 45 unchanged lines hidden (view full) --- 333#endif 334 local_paca->mce_info->mce_ue_count--; 335 } 336} 337/* 338 * process pending MCE event from the mce event queue. This function will be 339 * called during syscall exit. 340 */ | 263} 264 265void mce_common_process_ue(struct pt_regs *regs, 266 struct mce_error_info *mce_err) 267{ 268 const struct exception_table_entry *entry; 269 270 entry = search_kernel_exception_table(regs->nip); --- 45 unchanged lines hidden (view full) --- 316#endif 317 local_paca->mce_info->mce_ue_count--; 318 } 319} 320/* 321 * process pending MCE event from the mce event queue. This function will be 322 * called during syscall exit. 323 */ |
341static void machine_check_process_queued_event(struct irq_work *work) | 324static void machine_check_process_queued_event(void) |
342{ 343 int index; 344 struct machine_check_event *evt; 345 346 add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE); 347 348 /* 349 * For now just print it to console. --- 8 unchanged lines hidden (view full) --- 358 local_paca->mce_info->mce_queue_count--; 359 continue; 360 } 361 machine_check_print_event_info(evt, false, false); 362 local_paca->mce_info->mce_queue_count--; 363 } 364} 365 | 325{ 326 int index; 327 struct machine_check_event *evt; 328 329 add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE); 330 331 /* 332 * For now just print it to console. --- 8 unchanged lines hidden (view full) --- 341 local_paca->mce_info->mce_queue_count--; 342 continue; 343 } 344 machine_check_print_event_info(evt, false, false); 345 local_paca->mce_info->mce_queue_count--; 346 } 347} 348 |
349void set_mce_pending_irq_work(void) 350{ 351 local_paca->mce_pending_irq_work = 1; 352} 353 354void clear_mce_pending_irq_work(void) 355{ 356 local_paca->mce_pending_irq_work = 0; 357} 358 359void mce_run_irq_context_handlers(void) 360{ 361 if (unlikely(local_paca->mce_pending_irq_work)) { 362 if (ppc_md.machine_check_log_err) 363 ppc_md.machine_check_log_err(); 364 machine_check_process_queued_event(); 365 machine_check_ue_work(); 366 clear_mce_pending_irq_work(); 367 } 368} 369 |
|
366void machine_check_print_event_info(struct machine_check_event *evt, 367 bool user_mode, bool in_guest) 368{ 369 const char *level, *sevstr, *subtype, *err_type, *initiator; 370 uint64_t ea = 0, pa = 0; 371 int n = 0; 372 char dar_str[50]; 373 char pa_str[50]; --- 391 unchanged lines hidden --- | 370void machine_check_print_event_info(struct machine_check_event *evt, 371 bool user_mode, bool in_guest) 372{ 373 const char *level, *sevstr, *subtype, *err_type, *initiator; 374 uint64_t ea = 0, pa = 0; 375 int n = 0; 376 char dar_str[50]; 377 char pa_str[50]; --- 391 unchanged lines hidden --- |