Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | /* |
2 | * ========== Copyright Header Begin ========================================== | |
3 | * | |
4 | * OpenSPARC T2 Processor File: ncu.h | |
5 | * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
6 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES. | |
7 | * | |
8 | * The above named program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public | |
10 | * License version 2 as published by the Free Software Foundation. | |
11 | * | |
12 | * The above named program is distributed in the hope that it will be | |
13 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public | |
18 | * License along with this work; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. | |
20 | * | |
21 | * ========== Copyright Header End ============================================ | |
22 | */ | |
23 | #ifndef __NCU_H__ | |
24 | #define __NCU_H__ | |
25 | ||
26 | ||
27 | /* | |
28 | * this is the niagara2 ncu module. the original source is taken from legion | |
29 | * with minor/cosmetic modifications. The name of the relevent functions is | |
30 | * kept same as in legion so as to allow easy updates. | |
31 | * | |
32 | * The original source has related CSRs, which are not needed for this | |
33 | * module, but are still added(though incomplete in certain instances) in case | |
34 | * we need it in future. | |
35 | */ | |
36 | #include "pthread.h" | |
37 | #include <assert.h> | |
38 | #include "module.h" | |
39 | #include "types.h" | |
40 | #include "vcpu.h" | |
41 | #include "cpu_interface.h" | |
42 | ||
43 | static const char* piu_regions[] = {"cfgio","mem32","mem64","piu_8mb","unknown"}; | |
44 | extern "C"{ | |
45 | static int access_ncu(uint32_t cpuid, void* obj, uint64_t paddr, mmi_bool_t wr, uint32_t size, uint64_t* buf, uint8_t bytemask); | |
46 | int n2ncu_ui_cmd(void*, int argc, char * argv[]); | |
47 | } | |
48 | ||
49 | ||
50 | class n2Ncu:public Module{ | |
51 | public: | |
52 | ||
53 | #define MASK64( _high, _low ) ( ( (uint64_t)((~(uint64_t)0)>>(63-(_high))) ) & ( (uint64_t)( (~(uint64_t)0)<<(_low)) ) ) | |
54 | #define GETMASK64(x, hi, lo) (((uint64_t)(x) & MASK64((hi), (lo)))>>(lo)) | |
55 | /* src/procs/sunsparc/libniagara2/include/niagara2_device.h */ | |
56 | ||
57 | static const uint64_t NCU_CSR_BASE = 0x8000000000; | |
58 | static const uint64_t NCU_CSR_SIZE = 0x100000000; | |
59 | static const uint64_t PIU_MAX_REGION = 4; | |
60 | static const uint64_t NCU_REG_MASK = 0x4ffff; | |
61 | static const uint64_t NCU_TARGETS = 64; /* number of virtual cores */ | |
62 | static const uint64_t NCU_DEV_MAX = 128; /* max number of device Ids */ | |
63 | static const uint64_t NCU_DEV_ERR = 1; /* device Id for ECC error */ | |
64 | static const uint64_t NCU_DEV_SSI = 2; /* device Id for SSI interrupt */ | |
65 | static const uint64_t NCU_DEV_NIU_LB = 64; /* device Id range for NIU interrupt */ | |
66 | static const uint64_t NCU_DEV_NIU_UB = NCU_DEV_MAX-1; | |
67 | static const uint64_t NCU_MONDO_INT_MASK = 0x40fff; | |
68 | static const uint64_t NCU_MONDO_INT_BUSY = MASK64(6,6); | |
69 | static const uint64_t NCU_SOC_MASK = MASK64(42,40)|MASK64(38,37)|MASK64(35,34)|MASK64(32,31)|MASK64(29,0); | |
70 | static const uint64_t NCU_INT_MAN_MASK = NCU_DEV_MAX*8; | |
71 | ||
72 | uint64_t NCU_INT_MAN_CPUID(uint64_t n){ return ((n&MASK64(13,8))>>8); } | |
73 | static const uint64_t NCU_INT_ACK = 0; | |
74 | static const uint64_t NCU_INT_NACK = -1; | |
75 | ||
76 | static const uint64_t PIU_REGION_OFFSET_MASK = MASK64(35,24); | |
77 | static const uint64_t PIU_REGION_OFFSET_MASK_HI = MASK64(39,36); | |
78 | ||
79 | struct ncu_reg_t{ | |
80 | uint64_t int_man[NCU_DEV_MAX]; | |
81 | uint64_t mondo_int_vec; | |
82 | uint64_t ser_num; | |
83 | uint64_t efu_stat; | |
84 | uint64_t bank_enb; | |
85 | uint64_t bank_enb_stat; | |
86 | uint64_t l2_idx_hash_en; | |
87 | uint64_t l2_idx_hash_en_stat; | |
88 | uint64_t pcie_a_mem32_offset_base; | |
89 | uint64_t pcie_a_mem32_offset_mask; | |
90 | uint64_t pcie_a_mem64_offset_base; | |
91 | uint64_t pcie_a_mem64_offset_mask; | |
92 | uint64_t pcie_a_iocon_offset_base; | |
93 | uint64_t pcie_a_iocon_offset_mask; | |
94 | uint64_t pcie_a_fsh; | |
95 | uint64_t soc_esr; | |
96 | uint64_t soc_log_enb; | |
97 | uint64_t soc_intr_enb; | |
98 | uint64_t soc_err_inject; | |
99 | uint64_t soc_fatal_enb; | |
100 | uint64_t soc_sii_err_syndrome; | |
101 | uint64_t soc_ncu_err_syndrome; | |
102 | uint64_t mondo_int_data0[NCU_TARGETS]; | |
103 | uint64_t mondo_int_data1[NCU_TARGETS]; | |
104 | uint64_t mondo_int_busy[NCU_TARGETS]; | |
105 | }; | |
106 | ||
107 | struct map_info_t{ | |
108 | uint64_t base; | |
109 | uint64_t mask; | |
110 | uint64_t size; | |
111 | int func; | |
112 | bool enable; | |
113 | uint8_t priority; | |
114 | int align_size; | |
115 | int reverse_endian; | |
116 | ||
117 | void info(){ | |
118 | printf("base<%llx>size<%llx>mask<%llx>en<%d>\n",base,size,mask,enable); | |
119 | } | |
120 | ||
121 | }; | |
122 | ||
123 | enum piu_region_t{ | |
124 | PIU_REGION_CFGIO = 0, | |
125 | PIU_REGION_MEM32 = 1, | |
126 | PIU_REGION_MEM64 = 2, | |
127 | PIU_REGION_8MB = 3, | |
128 | PIU_REGION_UNMAPPED | |
129 | }; | |
130 | ||
131 | enum ncu_reg_offset_t{ | |
132 | INT_MAN = 0x00000, | |
133 | MONDO_INT_VEC = 0x00a00, | |
134 | SER_NUM = 0x01000, | |
135 | EFU_STAT = 0x01008, | |
136 | CORE_AVAIL = 0x01010,/* same as ASI_CORE_AVAILABLE */ | |
137 | BANK_AVAIL = 0x01018, | |
138 | BANK_ENABLE = 0x01020, | |
139 | BANK_ENABLE_STATUS = 0x01028, | |
140 | L2_IDX_HASH_EN = 0x01030, | |
141 | L2_IDX_HASH_EN_STATUS = 0x01038, | |
142 | PCIE_A_MEM32_OFFSET_BASE = 0x02000, | |
143 | PCIE_A_MEM32_OFFSET_MASK = 0x02008, | |
144 | PCIE_A_MEM64_OFFSET_BASE = 0x02010, | |
145 | PCIE_A_MEM64_OFFSET_MASK = 0x02018, | |
146 | PCIE_A_IOCON_OFFSET_BASE = 0x02020, | |
147 | PCIE_A_IOCON_OFFSET_MASK = 0x02028, | |
148 | PCIE_A_FSH = 0x02030, | |
149 | SOC_ESR = 0x03000, | |
150 | SOC_LOG_ENABLE = 0x03008, | |
151 | SOC_INTERRUPT_ENABLE = 0x03010, | |
152 | SOC_ERROR_INJECTION = 0x03018, | |
153 | SOC_FATAL_ERROR_ENABLE = 0x03020, | |
154 | SOC_PENDING_ERROR_STATUS = 0x03028,/* same as SOC_ESR */ | |
155 | SOC_SII_ERROR_SYNDROME = 0x03030, | |
156 | SOC_NCU_ERROR_SYNDROME = 0x03038, | |
157 | MONDO_INT_DATA0 = 0x40000, | |
158 | MONDO_INT_DATA1 = 0x40200, | |
159 | MONDO_INT_ADATA0 = 0x40400, | |
160 | MONDO_INT_ADATA1 = 0x40600, | |
161 | MONDO_INT_BUSY = 0x40800, | |
162 | MONDO_INT_ABUSY = 0x40a00 | |
163 | }; | |
164 | ||
165 | /* | |
166 | * XXX need an interface to read asi registers from vonk to add support for | |
167 | * ASI registers available through NCU | |
168 | */ | |
169 | ||
170 | ||
171 | /* | |
172 | * a list of registers that will be dumped and restored by this module. | |
173 | * in case more registers are added, or some offsets change or any | |
174 | * incompatible change happens, and there exist dumps with old format that need to be | |
175 | * supported, then create a new dumpRegsV2[]. The restore | |
176 | * function should be able to differtiate and handle correctly the | |
177 | * different versions. Otherwise just modify the V1 array and dump/restore | |
178 | * functions as needed. | |
179 | */ | |
180 | static const uint64_t dumpRegsV1[25]; | |
181 | ||
182 | private: | |
183 | ||
184 | const char * current_dump_version; | |
185 | ||
186 | bool UINT64_RANGE_CHECK(uint64_t _low, uint64_t _val, uint64_t _high){ | |
187 | return ((_val - _low) < (_high - _low)); | |
188 | } | |
189 | ||
190 | void ASSIGN_NCU(uint64_t& _n,uint64_t _m,uint64_t val, uint64_t offset){ | |
191 | _n = val; | |
192 | if(0LL != (val & ~(_m))) | |
193 | debug_err("%s: WARNING: attempt to write to reserved field in NCU\n" | |
194 | " Write 0x%llx to register %s (offset %llx)\n", | |
195 | getName(), val, ncu_reg_name(offset),offset); | |
196 | debug_more("%s: assigned %llx to register %s\n",getName(),val,ncu_reg_name(offset)); | |
197 | ||
198 | } | |
199 | const char *ncu_reg_name(uint64_t reg); | |
200 | void niagara2_pcie_mapping(piu_region_t region); | |
201 | ||
202 | ||
203 | ||
204 | ||
205 | public: // external interface fns. that can be called by other modules/system | |
206 | int access_regs(uint32_t cpuid, uint64_t paddr, mmi_bool_t wr, uint32_t size,\ | |
207 | uint64_t* buf, uint8_t bytemask); | |
208 | const map_info_t* getMap(piu_region_t region){ return &map[region]; } | |
209 | ||
210 | // send mondo to target strand. return either ACK = 0, or NACK = -1 | |
211 | int sendPiuMondo(VCPU_InterruptRequest * r){ | |
212 | extern Vcpu *g_vcpu[NCPU_MAX]; | |
213 | debug_more("%s:sending interrupt to strand %x\n",getName(),r->itid); | |
214 | ||
215 | int vector = regs.mondo_int_vec & 0x3f; | |
216 | int target = r->itid; | |
217 | int busy = regs.mondo_int_busy[target] >> 6 & 0x1; | |
218 | ||
219 | if(busy) | |
220 | return NCU_INT_NACK; | |
221 | ||
222 | regs.mondo_int_data0[target] = r->data[0]; | |
223 | regs.mondo_int_data1[target] = r->data[1]; | |
224 | regs.mondo_int_busy[target] = 1 << 6; | |
225 | ||
226 | r->data[7] = vector; | |
227 | Vcpu *vcpu = get_vcpu(target); | |
228 | if (!vcpu) | |
229 | return NCU_INT_NACK; | |
230 | vcpu->interrupt(r); | |
231 | return NCU_INT_ACK; | |
232 | } | |
233 | ||
234 | int sendNiuMondo(VCPU_InterruptRequest * r){ | |
235 | extern Vcpu *g_vcpu[NCPU_MAX]; | |
236 | ||
237 | int vector = regs.int_man[r->isid] & 0x3f; | |
238 | int target = r->itid; | |
239 | ||
240 | r->data[7] = vector; | |
241 | ||
242 | debug_more("%s:sending NIU interrupt tid:%x sid/ldg:%x vector:0x%x\n",getName(),r->itid, r->isid, vector); | |
243 | ||
244 | Vcpu *vcpu = get_vcpu(target); | |
245 | if (!vcpu) | |
246 | return NCU_INT_NACK; | |
247 | vcpu->interrupt(r); | |
248 | return NCU_INT_ACK; | |
249 | } | |
250 | ||
251 | void handle_ui(int argc, char * argv[]); | |
252 | void ui_cmd_usage(){ | |
253 | printf("ui format: %s <command> <command args> ... \n",getName()); | |
254 | printf("%s supports following UI commands\n",getName()); | |
255 | printf(" dump [<filename>]\n\ | |
256 | dump the CSR contents to \'filename\' \n\ | |
257 | default is stderr\n\ | |
258 | dump format is: <csr name> <csr offset> <csr value>\n"); | |
259 | printf(" restore <filename>\n\ | |
260 | restore the CSR contents from \'filename\' \n\ | |
261 | restore file format is same as dump file format\n"); | |
262 | printf(" debug [<level>]\n\ | |
263 | set the debug level for debug prints to \'level\'\n\ | |
264 | if \'level\' not provided, print current debug level\n\ | |
265 | \'level\' = [0|1|2]\n"); | |
266 | } | |
267 | ||
268 | public: // module interface | |
269 | ||
270 | const char *get_help(){ return Module::get_help_string(); } | |
271 | bool parse_arg(const char *){ return true; } | |
272 | bool check_args(){return true; } | |
273 | void init_done(){ | |
274 | mmi_map_physio(NCU_CSR_BASE,NCU_CSR_SIZE,(void*)this,access_ncu); | |
275 | return; | |
276 | } | |
277 | void module_added(mmi_instance_t, const char*){ return; } | |
278 | void module_deleted(mmi_instance_t, const char*){ return; } | |
279 | void modinfo(){ | |
280 | printf("%s: N2 NCU module\n" | |
281 | "iomap base<%llx size<%llx>\n",getName(), NCU_CSR_BASE,NCU_CSR_SIZE); | |
282 | printf("PCIE MAP -->\n"); | |
283 | for(int i = 0; i < 3; i++){ | |
284 | printf("%s",piu_regions[i]); | |
285 | map[i].info(); | |
286 | } | |
287 | } | |
288 | void *get_interface(const char*){ return (void*)this; } | |
289 | const char *get_version(){ return "1.0"; } | |
290 | ||
291 | bool dump(FILE *fp); | |
292 | bool dump_v1(FILE *fp); | |
293 | bool restore(FILE *fp); | |
294 | bool restore_v1(FILE *fp); | |
295 | ||
296 | n2Ncu(const char *_modname, const char *_instance_name); | |
297 | ~n2Ncu(){} | |
298 | private: | |
299 | ||
300 | ncu_reg_t regs; | |
301 | map_info_t map[PIU_MAX_REGION]; | |
302 | int node_id; | |
303 | pthread_mutex_t ncu_lock; | |
304 | ||
305 | void ncu_init(); | |
306 | ||
307 | }; | |
308 | ||
309 | #endif // __NCU_H__ | |
310 | ||
311 |