1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
|
/* SPDX-License-Identifier: MIT */
/*
* Copyright 2025 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef __RAS_UMC_H__
#define __RAS_UMC_H__
#include "ras.h"
#include "eeprom.h"
#include "cmd.h"
#define UMC_VRAM_TYPE_UNKNOWN 0
#define UMC_VRAM_TYPE_GDDR1 1
#define UMC_VRAM_TYPE_DDR2 2
#define UMC_VRAM_TYPE_GDDR3 3
#define UMC_VRAM_TYPE_GDDR4 4
#define UMC_VRAM_TYPE_GDDR5 5
#define UMC_VRAM_TYPE_HBM 6
#define UMC_VRAM_TYPE_DDR3 7
#define UMC_VRAM_TYPE_DDR4 8
#define UMC_VRAM_TYPE_GDDR6 9
#define UMC_VRAM_TYPE_DDR5 10
#define UMC_VRAM_TYPE_LPDDR4 11
#define UMC_VRAM_TYPE_LPDDR5 12
#define UMC_VRAM_TYPE_HBM3E 13
#define UMC_ECC_NEW_DETECTED_TAG 0x1
#define UMC_INV_MEM_PFN (0xFFFFFFFFFFFFFFFF)
/* invalid node instance value */
#define UMC_INV_AID_NODE 0xffff
/*
* a flag to indicate v2 format channel index stored in eeprom
*
* v1: store channel index within a umc instance in eeprom
* range in UMC v12: 0 ~ 7
* v2: store global channel index in eeprom
* range in UMC v12: 0 ~ 127
*
* NOTE: it's better to store it in eeprom_table_record.mem_channel,
* but there is only 8 bits in mem_channel, and the channel number may
* increase in the future, we decide to save it in
* eeprom_table_record.retired_page. retired_page is useless in v2,
* we depend on eeprom_table_record.address instead of retired_page in v2.
* Only 48 bits are saved on eeprom, use bit 47 here.
*
* UMC_CHANNEL_IDX_V2 is replaced by nps value in cur_nps_retired_row_pfn
* in eeprom v3 format, so they have no conflict.
*/
#define UMC_CHANNEL_IDX_V2 BIT_ULL(47)
/* three column bits and one row bit in MCA address flip
* in bad page retirement
*/
#define UMC_PA_FLIP_BITS_NUM 4
/* bits [63:58] of pa carry the nps mode for RAS_TA_PA_TO_MCA,
* RAS TA will use it to get the nps related to pa
*/
#define UMC_PA_NPS_SHIFT 58
enum umc_memory_partition_mode {
UMC_MEMORY_PARTITION_MODE_NONE = 0,
UMC_MEMORY_PARTITION_MODE_NPS1 = 1,
UMC_MEMORY_PARTITION_MODE_NPS2 = 2,
UMC_MEMORY_PARTITION_MODE_NPS3 = 3,
UMC_MEMORY_PARTITION_MODE_NPS4 = 4,
UMC_MEMORY_PARTITION_MODE_NPS6 = 6,
UMC_MEMORY_PARTITION_MODE_NPS8 = 8,
UMC_MEMORY_PARTITION_MODE_UNKNOWN
};
struct ras_core_context;
struct ras_bank_ecc;
struct umc_flip_bits {
uint32_t flip_bits_in_pa[UMC_PA_FLIP_BITS_NUM];
uint32_t flip_row_bit;
uint32_t r13_in_pa;
uint32_t bit_num;
};
struct umc_mca_addr {
uint64_t err_addr;
uint32_t ch_inst;
uint32_t umc_inst;
uint32_t node_inst;
uint32_t socket_id;
};
struct umc_phy_addr {
uint64_t pa;
uint32_t bank;
uint32_t channel_idx;
};
struct umc_bank_addr {
uint32_t stack_id; /* SID */
uint32_t bank_group;
uint32_t bank;
uint32_t row;
uint32_t column;
uint32_t channel;
uint32_t subchannel; /* Also called Pseudochannel (PC) */
};
struct ras_umc_ip_func {
int (*bank_to_eeprom_record)(struct ras_core_context *ras_core,
struct ras_bank_ecc *bank, struct eeprom_umc_record *record);
int (*eeprom_record_to_nps_pages)(struct ras_core_context *ras_core,
struct eeprom_umc_record *record, uint32_t nps,
uint64_t *pfns, uint32_t num);
int (*bank_to_soc_pa)(struct ras_core_context *ras_core,
struct umc_bank_addr bank_addr, uint64_t *soc_pa);
int (*soc_pa_to_bank)(struct ras_core_context *ras_core,
uint64_t soc_pa, struct umc_bank_addr *bank_addr);
void (*mca_ipid_parse)(struct ras_core_context *ras_core, uint64_t ipid,
uint32_t *did, uint32_t *ch, uint32_t *umc_inst, uint32_t *sid);
int (*ma2pa)(struct ras_core_context *ras_core,
struct umc_mca_addr *addr_in, struct umc_phy_addr *addr_out,
uint32_t nps);
uint64_t (*nps_pa_to_row_pa)(struct ras_core_context *ras_core,
uint64_t pa, enum umc_memory_partition_mode nps, bool zero_pfn_ok);
uint32_t (*get_die_id)(uint64_t mca_addr, uint64_t pa);
};
struct eeprom_store_record {
/* point to data records array */
struct eeprom_umc_record *bps;
/* the count of entries */
int count;
/* the space can place new entries */
int space_left;
/* logical bad page number */
int bad_page_num;
/* the bad page number is ras_num_recs or
* ras_num_recs * retire_unit
*/
int bad_page_num_old;
};
struct ras_umc_err_data {
struct eeprom_store_record rom_data;
struct eeprom_store_record ram_data;
enum umc_memory_partition_mode umc_nps_mode;
uint64_t last_retired_pfn;
};
struct ras_umc {
u32 umc_ip_version;
u32 umc_vram_type;
u32 num_umc;
const struct ras_umc_ip_func *ip_func;
struct radix_tree_root root;
struct mutex tree_lock;
struct mutex umc_lock;
struct mutex bank_log_lock;
struct mutex pending_ecc_lock;
struct ras_umc_err_data umc_err_data;
struct list_head pending_ecc_list;
/* number of entries currently queued on pending_ecc_list */
u32 pending_ecc_count;
/* number of entries dropped because pending_ecc_list was full */
u32 pending_ecc_dropped;
};
/*
* Upper bound on entries that can be queued on pending_ecc_list while a
* GPU reset is in progress. Beyond this, new ECC events are dropped to
* prevent unbounded kernel memory growth in case of an ECC storm or
* malicious/repeated UMC error injection.
*/
#define RAS_UMC_PENDING_ECC_MAX 8192
int ras_umc_sw_init(struct ras_core_context *ras);
int ras_umc_sw_fini(struct ras_core_context *ras);
int ras_umc_hw_init(struct ras_core_context *ras);
int ras_umc_hw_fini(struct ras_core_context *ras);
int ras_umc_psp_ma2pa(struct ras_core_context *ras_core,
struct umc_mca_addr *in, struct umc_phy_addr *out,
uint32_t nps);
int ras_umc_handle_bad_pages(struct ras_core_context *ras_core, void *data);
int ras_umc_log_bad_bank(struct ras_core_context *ras, struct ras_bank_ecc *bank);
int ras_umc_log_bad_bank_pending(struct ras_core_context *ras_core, struct ras_bank_ecc *bank);
int ras_umc_log_pending_bad_bank(struct ras_core_context *ras_core);
int ras_umc_clear_logged_ecc(struct ras_core_context *ras_core);
int ras_umc_load_bad_pages(struct ras_core_context *ras_core);
int ras_umc_get_saved_eeprom_count(struct ras_core_context *ras_core);
int ras_umc_clean_badpage_data(struct ras_core_context *ras_core);
int ras_umc_fill_eeprom_record(struct ras_core_context *ras_core,
uint64_t err_addr, uint32_t umc_inst, struct umc_phy_addr *cur_nps_addr,
enum umc_memory_partition_mode cur_nps, struct eeprom_umc_record *record);
int ras_umc_get_badpage_count(struct ras_core_context *ras_core);
int ras_umc_get_badpage_record(struct ras_core_context *ras_core, uint32_t index, void *record);
bool ras_umc_check_retired_addr(struct ras_core_context *ras_core, uint64_t addr);
int ras_umc_translate_soc_pa_and_bank(struct ras_core_context *ras_core,
uint64_t *soc_pa, struct umc_bank_addr *bank_addr, bool bank_to_pa);
int ras_umc_convert_record_to_nps_pages(struct ras_core_context *ras_core,
struct eeprom_umc_record *record, uint32_t nps,
uint64_t *page_pfn, uint32_t max_pages);
uint32_t ras_umc_bit_wise_xor(uint32_t val);
int ras_umc_ma2pa(struct ras_core_context *ras_core,
struct umc_mca_addr *addr_in, struct umc_phy_addr *addr_out,
uint32_t nps);
#endif
|