162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Machine check exception header file.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright 2013 IBM Corporation
662306a36Sopenharmony_ci * Author: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#ifndef __ASM_PPC64_MCE_H__
1062306a36Sopenharmony_ci#define __ASM_PPC64_MCE_H__
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/bitops.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_cienum MCE_Version {
1562306a36Sopenharmony_ci	MCE_V1 = 1,
1662306a36Sopenharmony_ci};
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_cienum MCE_Severity {
1962306a36Sopenharmony_ci	MCE_SEV_NO_ERROR = 0,
2062306a36Sopenharmony_ci	MCE_SEV_WARNING = 1,
2162306a36Sopenharmony_ci	MCE_SEV_SEVERE = 2,
2262306a36Sopenharmony_ci	MCE_SEV_FATAL = 3,
2362306a36Sopenharmony_ci};
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cienum MCE_Disposition {
2662306a36Sopenharmony_ci	MCE_DISPOSITION_RECOVERED = 0,
2762306a36Sopenharmony_ci	MCE_DISPOSITION_NOT_RECOVERED = 1,
2862306a36Sopenharmony_ci};
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_cienum MCE_Initiator {
3162306a36Sopenharmony_ci	MCE_INITIATOR_UNKNOWN = 0,
3262306a36Sopenharmony_ci	MCE_INITIATOR_CPU = 1,
3362306a36Sopenharmony_ci	MCE_INITIATOR_PCI = 2,
3462306a36Sopenharmony_ci	MCE_INITIATOR_ISA = 3,
3562306a36Sopenharmony_ci	MCE_INITIATOR_MEMORY= 4,
3662306a36Sopenharmony_ci	MCE_INITIATOR_POWERMGM = 5,
3762306a36Sopenharmony_ci};
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_cienum MCE_ErrorType {
4062306a36Sopenharmony_ci	MCE_ERROR_TYPE_UNKNOWN = 0,
4162306a36Sopenharmony_ci	MCE_ERROR_TYPE_UE = 1,
4262306a36Sopenharmony_ci	MCE_ERROR_TYPE_SLB = 2,
4362306a36Sopenharmony_ci	MCE_ERROR_TYPE_ERAT = 3,
4462306a36Sopenharmony_ci	MCE_ERROR_TYPE_TLB = 4,
4562306a36Sopenharmony_ci	MCE_ERROR_TYPE_USER = 5,
4662306a36Sopenharmony_ci	MCE_ERROR_TYPE_RA = 6,
4762306a36Sopenharmony_ci	MCE_ERROR_TYPE_LINK = 7,
4862306a36Sopenharmony_ci	MCE_ERROR_TYPE_DCACHE = 8,
4962306a36Sopenharmony_ci	MCE_ERROR_TYPE_ICACHE = 9,
5062306a36Sopenharmony_ci};
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_cienum MCE_ErrorClass {
5362306a36Sopenharmony_ci	MCE_ECLASS_UNKNOWN = 0,
5462306a36Sopenharmony_ci	MCE_ECLASS_HARDWARE,
5562306a36Sopenharmony_ci	MCE_ECLASS_HARD_INDETERMINATE,
5662306a36Sopenharmony_ci	MCE_ECLASS_SOFTWARE,
5762306a36Sopenharmony_ci	MCE_ECLASS_SOFT_INDETERMINATE,
5862306a36Sopenharmony_ci};
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_cienum MCE_UeErrorType {
6162306a36Sopenharmony_ci	MCE_UE_ERROR_INDETERMINATE = 0,
6262306a36Sopenharmony_ci	MCE_UE_ERROR_IFETCH = 1,
6362306a36Sopenharmony_ci	MCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH = 2,
6462306a36Sopenharmony_ci	MCE_UE_ERROR_LOAD_STORE = 3,
6562306a36Sopenharmony_ci	MCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE = 4,
6662306a36Sopenharmony_ci};
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_cienum MCE_SlbErrorType {
6962306a36Sopenharmony_ci	MCE_SLB_ERROR_INDETERMINATE = 0,
7062306a36Sopenharmony_ci	MCE_SLB_ERROR_PARITY = 1,
7162306a36Sopenharmony_ci	MCE_SLB_ERROR_MULTIHIT = 2,
7262306a36Sopenharmony_ci};
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_cienum MCE_EratErrorType {
7562306a36Sopenharmony_ci	MCE_ERAT_ERROR_INDETERMINATE = 0,
7662306a36Sopenharmony_ci	MCE_ERAT_ERROR_PARITY = 1,
7762306a36Sopenharmony_ci	MCE_ERAT_ERROR_MULTIHIT = 2,
7862306a36Sopenharmony_ci};
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_cienum MCE_TlbErrorType {
8162306a36Sopenharmony_ci	MCE_TLB_ERROR_INDETERMINATE = 0,
8262306a36Sopenharmony_ci	MCE_TLB_ERROR_PARITY = 1,
8362306a36Sopenharmony_ci	MCE_TLB_ERROR_MULTIHIT = 2,
8462306a36Sopenharmony_ci};
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_cienum MCE_UserErrorType {
8762306a36Sopenharmony_ci	MCE_USER_ERROR_INDETERMINATE = 0,
8862306a36Sopenharmony_ci	MCE_USER_ERROR_TLBIE = 1,
8962306a36Sopenharmony_ci	MCE_USER_ERROR_SCV = 2,
9062306a36Sopenharmony_ci};
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_cienum MCE_RaErrorType {
9362306a36Sopenharmony_ci	MCE_RA_ERROR_INDETERMINATE = 0,
9462306a36Sopenharmony_ci	MCE_RA_ERROR_IFETCH = 1,
9562306a36Sopenharmony_ci	MCE_RA_ERROR_IFETCH_FOREIGN = 2,
9662306a36Sopenharmony_ci	MCE_RA_ERROR_PAGE_TABLE_WALK_IFETCH = 3,
9762306a36Sopenharmony_ci	MCE_RA_ERROR_PAGE_TABLE_WALK_IFETCH_FOREIGN = 4,
9862306a36Sopenharmony_ci	MCE_RA_ERROR_LOAD = 5,
9962306a36Sopenharmony_ci	MCE_RA_ERROR_STORE = 6,
10062306a36Sopenharmony_ci	MCE_RA_ERROR_PAGE_TABLE_WALK_LOAD_STORE = 7,
10162306a36Sopenharmony_ci	MCE_RA_ERROR_PAGE_TABLE_WALK_LOAD_STORE_FOREIGN = 8,
10262306a36Sopenharmony_ci	MCE_RA_ERROR_LOAD_STORE_FOREIGN = 9,
10362306a36Sopenharmony_ci};
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_cienum MCE_LinkErrorType {
10662306a36Sopenharmony_ci	MCE_LINK_ERROR_INDETERMINATE = 0,
10762306a36Sopenharmony_ci	MCE_LINK_ERROR_IFETCH_TIMEOUT = 1,
10862306a36Sopenharmony_ci	MCE_LINK_ERROR_PAGE_TABLE_WALK_IFETCH_TIMEOUT = 2,
10962306a36Sopenharmony_ci	MCE_LINK_ERROR_LOAD_TIMEOUT = 3,
11062306a36Sopenharmony_ci	MCE_LINK_ERROR_STORE_TIMEOUT = 4,
11162306a36Sopenharmony_ci	MCE_LINK_ERROR_PAGE_TABLE_WALK_LOAD_STORE_TIMEOUT = 5,
11262306a36Sopenharmony_ci};
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_cistruct machine_check_event {
11562306a36Sopenharmony_ci	enum MCE_Version	version:8;
11662306a36Sopenharmony_ci	u8			in_use;
11762306a36Sopenharmony_ci	enum MCE_Severity	severity:8;
11862306a36Sopenharmony_ci	enum MCE_Initiator	initiator:8;
11962306a36Sopenharmony_ci	enum MCE_ErrorType	error_type:8;
12062306a36Sopenharmony_ci	enum MCE_ErrorClass	error_class:8;
12162306a36Sopenharmony_ci	enum MCE_Disposition	disposition:8;
12262306a36Sopenharmony_ci	bool			sync_error;
12362306a36Sopenharmony_ci	u16			cpu;
12462306a36Sopenharmony_ci	u64			gpr3;
12562306a36Sopenharmony_ci	u64			srr0;
12662306a36Sopenharmony_ci	u64			srr1;
12762306a36Sopenharmony_ci	union {
12862306a36Sopenharmony_ci		struct {
12962306a36Sopenharmony_ci			enum MCE_UeErrorType ue_error_type:8;
13062306a36Sopenharmony_ci			u8		effective_address_provided;
13162306a36Sopenharmony_ci			u8		physical_address_provided;
13262306a36Sopenharmony_ci			u8		ignore_event;
13362306a36Sopenharmony_ci			u8		reserved_1[4];
13462306a36Sopenharmony_ci			u64		effective_address;
13562306a36Sopenharmony_ci			u64		physical_address;
13662306a36Sopenharmony_ci			u8		reserved_2[8];
13762306a36Sopenharmony_ci		} ue_error;
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci		struct {
14062306a36Sopenharmony_ci			enum MCE_SlbErrorType slb_error_type:8;
14162306a36Sopenharmony_ci			u8		effective_address_provided;
14262306a36Sopenharmony_ci			u8		reserved_1[6];
14362306a36Sopenharmony_ci			u64		effective_address;
14462306a36Sopenharmony_ci			u8		reserved_2[16];
14562306a36Sopenharmony_ci		} slb_error;
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci		struct {
14862306a36Sopenharmony_ci			enum MCE_EratErrorType erat_error_type:8;
14962306a36Sopenharmony_ci			u8		effective_address_provided;
15062306a36Sopenharmony_ci			u8		reserved_1[6];
15162306a36Sopenharmony_ci			u64		effective_address;
15262306a36Sopenharmony_ci			u8		reserved_2[16];
15362306a36Sopenharmony_ci		} erat_error;
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci		struct {
15662306a36Sopenharmony_ci			enum MCE_TlbErrorType tlb_error_type:8;
15762306a36Sopenharmony_ci			u8		effective_address_provided;
15862306a36Sopenharmony_ci			u8		reserved_1[6];
15962306a36Sopenharmony_ci			u64		effective_address;
16062306a36Sopenharmony_ci			u8		reserved_2[16];
16162306a36Sopenharmony_ci		} tlb_error;
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci		struct {
16462306a36Sopenharmony_ci			enum MCE_UserErrorType user_error_type:8;
16562306a36Sopenharmony_ci			u8		effective_address_provided;
16662306a36Sopenharmony_ci			u8		reserved_1[6];
16762306a36Sopenharmony_ci			u64		effective_address;
16862306a36Sopenharmony_ci			u8		reserved_2[16];
16962306a36Sopenharmony_ci		} user_error;
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci		struct {
17262306a36Sopenharmony_ci			enum MCE_RaErrorType ra_error_type:8;
17362306a36Sopenharmony_ci			u8		effective_address_provided;
17462306a36Sopenharmony_ci			u8		reserved_1[6];
17562306a36Sopenharmony_ci			u64		effective_address;
17662306a36Sopenharmony_ci			u8		reserved_2[16];
17762306a36Sopenharmony_ci		} ra_error;
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci		struct {
18062306a36Sopenharmony_ci			enum MCE_LinkErrorType link_error_type:8;
18162306a36Sopenharmony_ci			u8		effective_address_provided;
18262306a36Sopenharmony_ci			u8		reserved_1[6];
18362306a36Sopenharmony_ci			u64		effective_address;
18462306a36Sopenharmony_ci			u8		reserved_2[16];
18562306a36Sopenharmony_ci		} link_error;
18662306a36Sopenharmony_ci	} u;
18762306a36Sopenharmony_ci};
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_cistruct mce_error_info {
19062306a36Sopenharmony_ci	enum MCE_ErrorType error_type:8;
19162306a36Sopenharmony_ci	union {
19262306a36Sopenharmony_ci		enum MCE_UeErrorType ue_error_type:8;
19362306a36Sopenharmony_ci		enum MCE_SlbErrorType slb_error_type:8;
19462306a36Sopenharmony_ci		enum MCE_EratErrorType erat_error_type:8;
19562306a36Sopenharmony_ci		enum MCE_TlbErrorType tlb_error_type:8;
19662306a36Sopenharmony_ci		enum MCE_UserErrorType user_error_type:8;
19762306a36Sopenharmony_ci		enum MCE_RaErrorType ra_error_type:8;
19862306a36Sopenharmony_ci		enum MCE_LinkErrorType link_error_type:8;
19962306a36Sopenharmony_ci	} u;
20062306a36Sopenharmony_ci	enum MCE_Severity	severity:8;
20162306a36Sopenharmony_ci	enum MCE_Initiator	initiator:8;
20262306a36Sopenharmony_ci	enum MCE_ErrorClass	error_class:8;
20362306a36Sopenharmony_ci	bool			sync_error;
20462306a36Sopenharmony_ci	bool			ignore_event;
20562306a36Sopenharmony_ci};
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci#define MAX_MC_EVT	10
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_cistruct mce_info {
21062306a36Sopenharmony_ci	int mce_nest_count;
21162306a36Sopenharmony_ci	struct machine_check_event mce_event[MAX_MC_EVT];
21262306a36Sopenharmony_ci	/* Queue for delayed MCE events. */
21362306a36Sopenharmony_ci	int mce_queue_count;
21462306a36Sopenharmony_ci	struct machine_check_event mce_event_queue[MAX_MC_EVT];
21562306a36Sopenharmony_ci	/* Queue for delayed MCE UE events. */
21662306a36Sopenharmony_ci	int mce_ue_count;
21762306a36Sopenharmony_ci	struct machine_check_event  mce_ue_event_queue[MAX_MC_EVT];
21862306a36Sopenharmony_ci};
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci/* Release flags for get_mce_event() */
22162306a36Sopenharmony_ci#define MCE_EVENT_RELEASE	true
22262306a36Sopenharmony_ci#define MCE_EVENT_DONTRELEASE	false
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_cistruct pt_regs;
22562306a36Sopenharmony_cistruct notifier_block;
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ciextern void save_mce_event(struct pt_regs *regs, long handled,
22862306a36Sopenharmony_ci			   struct mce_error_info *mce_err, uint64_t nip,
22962306a36Sopenharmony_ci			   uint64_t addr, uint64_t phys_addr);
23062306a36Sopenharmony_ciextern int get_mce_event(struct machine_check_event *mce, bool release);
23162306a36Sopenharmony_ciextern void release_mce_event(void);
23262306a36Sopenharmony_ciextern void machine_check_queue_event(void);
23362306a36Sopenharmony_ciextern void machine_check_print_event_info(struct machine_check_event *evt,
23462306a36Sopenharmony_ci					   bool user_mode, bool in_guest);
23562306a36Sopenharmony_ciunsigned long addr_to_pfn(struct pt_regs *regs, unsigned long addr);
23662306a36Sopenharmony_ciextern void mce_common_process_ue(struct pt_regs *regs,
23762306a36Sopenharmony_ci				  struct mce_error_info *mce_err);
23862306a36Sopenharmony_civoid mce_irq_work_queue(void);
23962306a36Sopenharmony_ciint mce_register_notifier(struct notifier_block *nb);
24062306a36Sopenharmony_ciint mce_unregister_notifier(struct notifier_block *nb);
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S_64
24362306a36Sopenharmony_civoid mce_run_irq_context_handlers(void);
24462306a36Sopenharmony_ci#else
24562306a36Sopenharmony_cistatic inline void mce_run_irq_context_handlers(void) { };
24662306a36Sopenharmony_ci#endif /* CONFIG_PPC_BOOK3S_64 */
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S_64
24962306a36Sopenharmony_civoid set_mce_pending_irq_work(void);
25062306a36Sopenharmony_civoid clear_mce_pending_irq_work(void);
25162306a36Sopenharmony_ci#endif /* CONFIG_PPC_BOOK3S_64 */
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S_64
25462306a36Sopenharmony_civoid flush_and_reload_slb(void);
25562306a36Sopenharmony_civoid flush_erat(void);
25662306a36Sopenharmony_cilong __machine_check_early_realmode_p7(struct pt_regs *regs);
25762306a36Sopenharmony_cilong __machine_check_early_realmode_p8(struct pt_regs *regs);
25862306a36Sopenharmony_cilong __machine_check_early_realmode_p9(struct pt_regs *regs);
25962306a36Sopenharmony_cilong __machine_check_early_realmode_p10(struct pt_regs *regs);
26062306a36Sopenharmony_ci#endif /* CONFIG_PPC_BOOK3S_64 */
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S_64
26362306a36Sopenharmony_civoid mce_init(void);
26462306a36Sopenharmony_ci#else
26562306a36Sopenharmony_cistatic inline void mce_init(void) { };
26662306a36Sopenharmony_ci#endif /* CONFIG_PPC_BOOK3S_64 */
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci#endif /* __ASM_PPC64_MCE_H__ */
269