Commit | Line | Data |
---|---|---|
952cf6d7 JS |
1 | /* |
2 | * This file is subject to the terms and conditions of the GNU General Public | |
3 | * License. See the file "COPYING" in the main directory of this archive | |
4 | * for more details. | |
5 | * | |
6 | * SGI UV architectural definitions | |
7 | * | |
7a6d94f0 | 8 | * (C) Copyright 2020 Hewlett Packard Enterprise Development LP |
5f40f7d9 | 9 | * Copyright (C) 2007-2014 Silicon Graphics, Inc. All rights reserved. |
952cf6d7 JS |
10 | */ |
11 | ||
05e4d316 PA |
12 | #ifndef _ASM_X86_UV_UV_HUB_H |
13 | #define _ASM_X86_UV_UV_HUB_H | |
952cf6d7 | 14 | |
bc5d9940 | 15 | #ifdef CONFIG_X86_64 |
952cf6d7 JS |
16 | #include <linux/numa.h> |
17 | #include <linux/percpu.h> | |
c08b6acc | 18 | #include <linux/timer.h> |
8dc579e8 | 19 | #include <linux/io.h> |
906f3b20 | 20 | #include <linux/topology.h> |
952cf6d7 JS |
21 | #include <asm/types.h> |
22 | #include <asm/percpu.h> | |
4fb7d087 | 23 | #include <asm/uv/uv.h> |
66666e50 | 24 | #include <asm/uv/uv_mmrs.h> |
c85375cd | 25 | #include <asm/uv/bios.h> |
02dd0a06 RH |
26 | #include <asm/irq_vectors.h> |
27 | #include <asm/io_apic.h> | |
952cf6d7 JS |
28 | |
29 | ||
30 | /* | |
31 | * Addressing Terminology | |
32 | * | |
9f5314fb JS |
33 | * M - The low M bits of a physical address represent the offset |
34 | * into the blade local memory. RAM memory on a blade is physically | |
35 | * contiguous (although various IO spaces may punch holes in | |
36 | * it).. | |
952cf6d7 | 37 | * |
39d30770 MT |
38 | * N - Number of bits in the node portion of a socket physical |
39 | * address. | |
9f5314fb | 40 | * |
39d30770 MT |
41 | * NASID - network ID of a router, Mbrick or Cbrick. Nasid values of |
42 | * routers always have low bit of 1, C/MBricks have low bit | |
43 | * equal to 0. Most addressing macros that target UV hub chips | |
44 | * right shift the NASID by 1 to exclude the always-zero bit. | |
45 | * NASIDs contain up to 15 bits. | |
9f5314fb JS |
46 | * |
47 | * GNODE - NASID right shifted by 1 bit. Most mmrs contain gnodes instead | |
48 | * of nasids. | |
49 | * | |
39d30770 MT |
50 | * PNODE - the low N bits of the GNODE. The PNODE is the most useful variant |
51 | * of the nasid for socket usage. | |
9f5314fb | 52 | * |
6a469e46 JS |
53 | * GPA - (global physical address) a socket physical address converted |
54 | * so that it can be used by the GRU as a global address. Socket | |
55 | * physical addresses 1) need additional NASID (node) bits added | |
56 | * to the high end of the address, and 2) unaliased if the | |
57 | * partition does not have a physical address 0. In addition, on | |
58 | * UV2 rev 1, GPAs need the gnode left shifted to bits 39 or 40. | |
59 | * | |
9f5314fb JS |
60 | * |
61 | * NumaLink Global Physical Address Format: | |
62 | * +--------------------------------+---------------------+ | |
63 | * |00..000| GNODE | NodeOffset | | |
64 | * +--------------------------------+---------------------+ | |
65 | * |<-------53 - M bits --->|<--------M bits -----> | |
66 | * | |
67 | * M - number of node offset bits (35 .. 40) | |
952cf6d7 JS |
68 | * |
69 | * | |
70 | * Memory/UV-HUB Processor Socket Address Format: | |
9f5314fb JS |
71 | * +----------------+---------------+---------------------+ |
72 | * |00..000000000000| PNODE | NodeOffset | | |
73 | * +----------------+---------------+---------------------+ | |
74 | * <--- N bits --->|<--------M bits -----> | |
952cf6d7 | 75 | * |
9f5314fb JS |
76 | * M - number of node offset bits (35 .. 40) |
77 | * N - number of PNODE bits (0 .. 10) | |
952cf6d7 JS |
78 | * |
79 | * Note: M + N cannot currently exceed 44 (x86_64) or 46 (IA64). | |
80 | * The actual values are configuration dependent and are set at | |
9f5314fb JS |
81 | * boot time. M & N values are set by the hardware/BIOS at boot. |
82 | * | |
952cf6d7 JS |
83 | * |
84 | * APICID format | |
39d30770 MT |
85 | * NOTE!!!!!! This is the current format of the APICID. However, code |
86 | * should assume that this will change in the future. Use functions | |
87 | * in this file for all APICID bit manipulations and conversion. | |
952cf6d7 | 88 | * |
39d30770 MT |
89 | * 1111110000000000 |
90 | * 5432109876543210 | |
2a919596 JS |
91 | * pppppppppplc0cch Nehalem-EX (12 bits in hdw reg) |
92 | * ppppppppplcc0cch Westmere-EX (12 bits in hdw reg) | |
93 | * pppppppppppcccch SandyBridge (15 bits in hdw reg) | |
952cf6d7 JS |
94 | * sssssssssss |
95 | * | |
9f5314fb | 96 | * p = pnode bits |
952cf6d7 JS |
97 | * l = socket number on board |
98 | * c = core | |
99 | * h = hyperthread | |
9f5314fb | 100 | * s = bits that are in the SOCKET_ID CSR |
952cf6d7 | 101 | * |
2a919596 | 102 | * Note: Processor may support fewer bits in the APICID register. The ACPI |
952cf6d7 JS |
103 | * tables hold all 16 bits. Software needs to be aware of this. |
104 | * | |
39d30770 MT |
105 | * Unless otherwise specified, all references to APICID refer to |
106 | * the FULL value contained in ACPI tables, not the subset in the | |
107 | * processor APICID register. | |
952cf6d7 JS |
108 | */ |
109 | ||
952cf6d7 JS |
110 | /* |
111 | * Maximum number of bricks in all partitions and in all coherency domains. | |
112 | * This is the total number of bricks accessible in the numalink fabric. It | |
113 | * includes all C & M bricks. Routers are NOT included. | |
114 | * | |
115 | * This value is also the value of the maximum number of non-router NASIDs | |
116 | * in the numalink fabric. | |
117 | * | |
9f5314fb | 118 | * NOTE: a brick may contain 1 or 2 OS nodes. Don't get these confused. |
952cf6d7 JS |
119 | */ |
120 | #define UV_MAX_NUMALINK_BLADES 16384 | |
121 | ||
122 | /* | |
123 | * Maximum number of C/Mbricks within a software SSI (hardware may support | |
124 | * more). | |
125 | */ | |
126 | #define UV_MAX_SSI_BLADES 256 | |
127 | ||
128 | /* | |
129 | * The largest possible NASID of a C or M brick (+ 2) | |
130 | */ | |
1d21e6e3 | 131 | #define UV_MAX_NASID_VALUE (UV_MAX_NUMALINK_BLADES * 2) |
952cf6d7 | 132 | |
c85375cd MT |
133 | /* GAM (globally addressed memory) range table */ |
134 | struct uv_gam_range_s { | |
135 | u32 limit; /* PA bits 56:26 (GAM_RANGE_SHFT) */ | |
136 | u16 nasid; /* node's global physical address */ | |
137 | s8 base; /* entry index of node's base addr */ | |
138 | u8 reserved; | |
139 | }; | |
140 | ||
952cf6d7 JS |
141 | /* |
142 | * The following defines attributes of the HUB chip. These attributes are | |
0045ddd2 MT |
143 | * frequently referenced and are kept in a common per hub struct. |
144 | * After setup, the struct is read only, so it should be readily | |
145 | * available in the L3 cache on the cpu socket for the node. | |
952cf6d7 JS |
146 | */ |
147 | struct uv_hub_info_s { | |
647128f1 MT |
148 | unsigned int hub_type; |
149 | unsigned char hub_revision; | |
69a72a0e | 150 | unsigned long global_mmr_base; |
1de329c1 | 151 | unsigned long global_mmr_shift; |
69a72a0e | 152 | unsigned long gpa_mask; |
6e27b91c MT |
153 | unsigned short *socket_to_node; |
154 | unsigned short *socket_to_pnode; | |
155 | unsigned short *pnode_to_socket; | |
c85375cd | 156 | struct uv_gam_range_s *gr_table; |
1de329c1 MT |
157 | unsigned short min_socket; |
158 | unsigned short min_pnode; | |
c85375cd MT |
159 | unsigned char m_val; |
160 | unsigned char n_val; | |
161 | unsigned char gr_table_len; | |
2a919596 | 162 | unsigned char apic_pnode_shift; |
1de329c1 | 163 | unsigned char gpa_shift; |
6c779442 | 164 | unsigned char nasid_shift; |
6a469e46 JS |
165 | unsigned char m_shift; |
166 | unsigned char n_lshift; | |
1de329c1 | 167 | unsigned int gnode_extra; |
69a72a0e MT |
168 | unsigned long gnode_upper; |
169 | unsigned long lowmem_remap_top; | |
170 | unsigned long lowmem_remap_base; | |
1de329c1 MT |
171 | unsigned long global_gru_base; |
172 | unsigned long global_gru_shift; | |
69a72a0e MT |
173 | unsigned short pnode; |
174 | unsigned short pnode_mask; | |
175 | unsigned short coherency_domain_number; | |
176 | unsigned short numa_blade_id; | |
906f3b20 MT |
177 | unsigned short nr_possible_cpus; |
178 | unsigned short nr_online_cpus; | |
179 | short memory_nid; | |
8a50c585 | 180 | unsigned short *node_to_socket; |
952cf6d7 | 181 | }; |
7f1baa06 | 182 | |
0045ddd2 MT |
183 | /* CPU specific info with a pointer to the hub common info struct */ |
184 | struct uv_cpu_info_s { | |
185 | void *p_uv_hub_info; | |
186 | unsigned char blade_cpu_id; | |
c4d98077 | 187 | void *reserved; |
0045ddd2 MT |
188 | }; |
189 | DECLARE_PER_CPU(struct uv_cpu_info_s, __uv_cpu_info); | |
190 | ||
191 | #define uv_cpu_info this_cpu_ptr(&__uv_cpu_info) | |
192 | #define uv_cpu_info_per(cpu) (&per_cpu(__uv_cpu_info, cpu)) | |
193 | ||
3edcf2ff MT |
194 | /* Node specific hub common info struct */ |
195 | extern void **__uv_hub_info_list; | |
196 | static inline struct uv_hub_info_s *uv_hub_info_list(int node) | |
197 | { | |
198 | return (struct uv_hub_info_s *)__uv_hub_info_list[node]; | |
199 | } | |
200 | ||
201 | static inline struct uv_hub_info_s *_uv_hub_info(void) | |
202 | { | |
203 | return (struct uv_hub_info_s *)uv_cpu_info->p_uv_hub_info; | |
204 | } | |
205 | #define uv_hub_info _uv_hub_info() | |
206 | ||
207 | static inline struct uv_hub_info_s *uv_cpu_hub_info(int cpu) | |
208 | { | |
209 | return (struct uv_hub_info_s *)uv_cpu_info_per(cpu)->p_uv_hub_info; | |
210 | } | |
211 | ||
647128f1 MT |
212 | static inline int uv_hub_type(void) |
213 | { | |
214 | return uv_hub_info->hub_type; | |
215 | } | |
216 | ||
217 | static inline __init void uv_hub_type_set(int uvmask) | |
218 | { | |
219 | uv_hub_info->hub_type = uvmask; | |
220 | } | |
221 | ||
222 | ||
2a919596 | 223 | /* |
0045ddd2 | 224 | * HUB revision ranges for each UV HUB architecture. |
2a919596 JS |
225 | * This is a software convention - NOT the hardware revision numbers in |
226 | * the hub chip. | |
227 | */ | |
2a919596 | 228 | #define UV2_HUB_REVISION_BASE 3 |
6edbd471 | 229 | #define UV3_HUB_REVISION_BASE 5 |
eb1e3461 | 230 | #define UV4_HUB_REVISION_BASE 7 |
8078d195 | 231 | #define UV4A_HUB_REVISION_BASE 8 /* UV4 (fixed) rev 2 */ |
6c779442 | 232 | #define UV5_HUB_REVISION_BASE 9 |
2a919596 | 233 | |
647128f1 MT |
234 | static inline int is_uv(int uvmask) { return uv_hub_type() & uvmask; } |
235 | static inline int is_uv1_hub(void) { return 0; } | |
236 | static inline int is_uv2_hub(void) { return is_uv(UV2); } | |
237 | static inline int is_uv3_hub(void) { return is_uv(UV3); } | |
238 | static inline int is_uv4a_hub(void) { return is_uv(UV4A); } | |
239 | static inline int is_uv4_hub(void) { return is_uv(UV4); } | |
6c779442 | 240 | static inline int is_uv5_hub(void) { return is_uv(UV5); } |
6edbd471 | 241 | |
647128f1 MT |
242 | /* |
243 | * UV4A is a revision of UV4. So on UV4A, both is_uv4_hub() and | |
244 | * is_uv4a_hub() return true, While on UV4, only is_uv4_hub() | |
245 | * returns true. So to get true results, first test if is UV4A, | |
246 | * then test if is UV4. | |
247 | */ | |
8078d195 | 248 | |
647128f1 MT |
249 | /* UVX class: UV2,3,4 */ |
250 | static inline int is_uvx_hub(void) { return is_uv(UVX); } | |
eb1e3461 | 251 | |
647128f1 | 252 | /* UVY class: UV5,..? */ |
6c779442 | 253 | static inline int is_uvy_hub(void) { return is_uv(UVY); } |
6edbd471 | 254 | |
647128f1 MT |
255 | /* Any UV Hubbed System */ |
256 | static inline int is_uv_hub(void) { return is_uv(UV_ANY); } | |
2a919596 | 257 | |
c8f730b1 RA |
258 | union uvh_apicid { |
259 | unsigned long v; | |
260 | struct uvh_apicid_s { | |
261 | unsigned long local_apic_mask : 24; | |
262 | unsigned long local_apic_shift : 5; | |
263 | unsigned long unused1 : 3; | |
264 | unsigned long pnode_mask : 24; | |
265 | unsigned long pnode_shift : 5; | |
266 | unsigned long unused2 : 3; | |
267 | } s; | |
268 | }; | |
269 | ||
952cf6d7 JS |
270 | /* |
271 | * Local & Global MMR space macros. | |
39d30770 MT |
272 | * Note: macros are intended to be used ONLY by inline functions |
273 | * in this file - not by other kernel code. | |
274 | * n - NASID (full 15-bit global nasid) | |
275 | * g - GNODE (full 15-bit global nasid, right shifted 1) | |
276 | * p - PNODE (local part of nsids, right shifted 1) | |
952cf6d7 | 277 | */ |
6c779442 MT |
278 | #define UV_NASID_TO_PNODE(n) \ |
279 | (((n) >> uv_hub_info->nasid_shift) & uv_hub_info->pnode_mask) | |
c4ed3f04 | 280 | #define UV_PNODE_TO_GNODE(p) ((p) |uv_hub_info->gnode_extra) |
6c779442 MT |
281 | #define UV_PNODE_TO_NASID(p) \ |
282 | (UV_PNODE_TO_GNODE(p) << uv_hub_info->nasid_shift) | |
952cf6d7 | 283 | |
2a919596 JS |
284 | #define UV2_LOCAL_MMR_BASE 0xfa000000UL |
285 | #define UV2_GLOBAL_MMR32_BASE 0xfc000000UL | |
286 | #define UV2_LOCAL_MMR_SIZE (32UL * 1024 * 1024) | |
287 | #define UV2_GLOBAL_MMR32_SIZE (32UL * 1024 * 1024) | |
288 | ||
6edbd471 MT |
289 | #define UV3_LOCAL_MMR_BASE 0xfa000000UL |
290 | #define UV3_GLOBAL_MMR32_BASE 0xfc000000UL | |
291 | #define UV3_LOCAL_MMR_SIZE (32UL * 1024 * 1024) | |
292 | #define UV3_GLOBAL_MMR32_SIZE (32UL * 1024 * 1024) | |
293 | ||
eb1e3461 | 294 | #define UV4_LOCAL_MMR_BASE 0xfa000000UL |
c4d98077 | 295 | #define UV4_GLOBAL_MMR32_BASE 0 |
eb1e3461 | 296 | #define UV4_LOCAL_MMR_SIZE (32UL * 1024 * 1024) |
c4d98077 | 297 | #define UV4_GLOBAL_MMR32_SIZE 0 |
eb1e3461 | 298 | |
6c779442 MT |
299 | #define UV5_LOCAL_MMR_BASE 0xfa000000UL |
300 | #define UV5_GLOBAL_MMR32_BASE 0 | |
301 | #define UV5_LOCAL_MMR_SIZE (32UL * 1024 * 1024) | |
302 | #define UV5_GLOBAL_MMR32_SIZE 0 | |
303 | ||
eb1e3461 | 304 | #define UV_LOCAL_MMR_BASE ( \ |
6c779442 MT |
305 | is_uv(UV2) ? UV2_LOCAL_MMR_BASE : \ |
306 | is_uv(UV3) ? UV3_LOCAL_MMR_BASE : \ | |
307 | is_uv(UV4) ? UV4_LOCAL_MMR_BASE : \ | |
308 | is_uv(UV5) ? UV5_LOCAL_MMR_BASE : \ | |
309 | 0) | |
eb1e3461 MT |
310 | |
311 | #define UV_GLOBAL_MMR32_BASE ( \ | |
6c779442 MT |
312 | is_uv(UV2) ? UV2_GLOBAL_MMR32_BASE : \ |
313 | is_uv(UV3) ? UV3_GLOBAL_MMR32_BASE : \ | |
314 | is_uv(UV4) ? UV4_GLOBAL_MMR32_BASE : \ | |
315 | is_uv(UV5) ? UV5_GLOBAL_MMR32_BASE : \ | |
316 | 0) | |
eb1e3461 MT |
317 | |
318 | #define UV_LOCAL_MMR_SIZE ( \ | |
6c779442 MT |
319 | is_uv(UV2) ? UV2_LOCAL_MMR_SIZE : \ |
320 | is_uv(UV3) ? UV3_LOCAL_MMR_SIZE : \ | |
321 | is_uv(UV4) ? UV4_LOCAL_MMR_SIZE : \ | |
322 | is_uv(UV5) ? UV5_LOCAL_MMR_SIZE : \ | |
323 | 0) | |
eb1e3461 MT |
324 | |
325 | #define UV_GLOBAL_MMR32_SIZE ( \ | |
6c779442 MT |
326 | is_uv(UV2) ? UV2_GLOBAL_MMR32_SIZE : \ |
327 | is_uv(UV3) ? UV3_GLOBAL_MMR32_SIZE : \ | |
328 | is_uv(UV4) ? UV4_GLOBAL_MMR32_SIZE : \ | |
329 | is_uv(UV5) ? UV5_GLOBAL_MMR32_SIZE : \ | |
330 | 0) | |
eb1e3461 | 331 | |
952cf6d7 JS |
332 | #define UV_GLOBAL_MMR64_BASE (uv_hub_info->global_mmr_base) |
333 | ||
56abcf24 JS |
334 | #define UV_GLOBAL_GRU_MMR_BASE 0x4000000 |
335 | ||
9f5314fb | 336 | #define UV_GLOBAL_MMR32_PNODE_SHIFT 15 |
1de329c1 MT |
337 | #define _UV_GLOBAL_MMR64_PNODE_SHIFT 26 |
338 | #define UV_GLOBAL_MMR64_PNODE_SHIFT (uv_hub_info->global_mmr_shift) | |
952cf6d7 | 339 | |
9f5314fb | 340 | #define UV_GLOBAL_MMR32_PNODE_BITS(p) ((p) << (UV_GLOBAL_MMR32_PNODE_SHIFT)) |
952cf6d7 | 341 | |
9f5314fb | 342 | #define UV_GLOBAL_MMR64_PNODE_BITS(p) \ |
67e83f30 | 343 | (((unsigned long)(p)) << UV_GLOBAL_MMR64_PNODE_SHIFT) |
9f5314fb | 344 | |
c8f730b1 | 345 | #define UVH_APICID 0x002D0E00L |
9f5314fb JS |
346 | #define UV_APIC_PNODE_SHIFT 6 |
347 | ||
7f1baa06 MT |
348 | /* Local Bus from cpu's perspective */ |
349 | #define LOCAL_BUS_BASE 0x1c00000 | |
350 | #define LOCAL_BUS_SIZE (4 * 1024 * 1024) | |
351 | ||
352 | /* | |
353 | * System Controller Interface Reg | |
354 | * | |
355 | * Note there are NO leds on a UV system. This register is only | |
356 | * used by the system controller to monitor system-wide operation. | |
d9f6e12f | 357 | * There are 64 regs per node. With Nehalem cpus (2 cores per node, |
7f1baa06 MT |
358 | * 8 cpus per core, 2 threads per cpu) there are 32 cpu threads on |
359 | * a node. | |
360 | * | |
361 | * The window is located at top of ACPI MMR space | |
362 | */ | |
363 | #define SCIR_WINDOW_COUNT 64 | |
364 | #define SCIR_LOCAL_MMR_BASE (LOCAL_BUS_BASE + \ | |
365 | LOCAL_BUS_SIZE - \ | |
366 | SCIR_WINDOW_COUNT) | |
367 | ||
368 | #define SCIR_CPU_HEARTBEAT 0x01 /* timer interrupt */ | |
369 | #define SCIR_CPU_ACTIVITY 0x02 /* not idle */ | |
370 | #define SCIR_CPU_HB_INTERVAL (HZ) /* once per second */ | |
371 | ||
8661984f DS |
372 | /* Loop through all installed blades */ |
373 | #define for_each_possible_blade(bid) \ | |
374 | for ((bid) = 0; (bid) < uv_num_possible_blades(); (bid)++) | |
375 | ||
9f5314fb JS |
376 | /* |
377 | * Macros for converting between kernel virtual addresses, socket local physical | |
378 | * addresses, and UV global physical addresses. | |
39d30770 MT |
379 | * Note: use the standard __pa() & __va() macros for converting |
380 | * between socket virtual and socket physical addresses. | |
9f5314fb JS |
381 | */ |
382 | ||
c85375cd MT |
383 | /* global bits offset - number of local address bits in gpa for this UV arch */ |
384 | static inline unsigned int uv_gpa_shift(void) | |
385 | { | |
386 | return uv_hub_info->gpa_shift; | |
387 | } | |
388 | #define _uv_gpa_shift | |
389 | ||
390 | /* Find node that has the address range that contains global address */ | |
391 | static inline struct uv_gam_range_s *uv_gam_range(unsigned long pa) | |
392 | { | |
393 | struct uv_gam_range_s *gr = uv_hub_info->gr_table; | |
394 | unsigned long pal = (pa & uv_hub_info->gpa_mask) >> UV_GAM_RANGE_SHFT; | |
395 | int i, num = uv_hub_info->gr_table_len; | |
396 | ||
397 | if (gr) { | |
398 | for (i = 0; i < num; i++, gr++) { | |
399 | if (pal < gr->limit) | |
400 | return gr; | |
401 | } | |
402 | } | |
403 | pr_crit("UV: GAM Range for 0x%lx not found at %p!\n", pa, gr); | |
404 | BUG(); | |
405 | } | |
406 | ||
407 | /* Return base address of node that contains global address */ | |
408 | static inline unsigned long uv_gam_range_base(unsigned long pa) | |
409 | { | |
410 | struct uv_gam_range_s *gr = uv_gam_range(pa); | |
411 | int base = gr->base; | |
412 | ||
413 | if (base < 0) | |
414 | return 0UL; | |
415 | ||
416 | return uv_hub_info->gr_table[base].limit; | |
417 | } | |
418 | ||
419 | /* socket phys RAM --> UV global NASID (UV4+) */ | |
420 | static inline unsigned long uv_soc_phys_ram_to_nasid(unsigned long paddr) | |
421 | { | |
422 | return uv_gam_range(paddr)->nasid; | |
423 | } | |
424 | #define _uv_soc_phys_ram_to_nasid | |
425 | ||
426 | /* socket virtual --> UV global NASID (UV4+) */ | |
427 | static inline unsigned long uv_gpa_nasid(void *v) | |
428 | { | |
429 | return uv_soc_phys_ram_to_nasid(__pa(v)); | |
430 | } | |
431 | ||
9f5314fb JS |
432 | /* socket phys RAM --> UV global physical address */ |
433 | static inline unsigned long uv_soc_phys_ram_to_gpa(unsigned long paddr) | |
434 | { | |
c85375cd MT |
435 | unsigned int m_val = uv_hub_info->m_val; |
436 | ||
9f5314fb | 437 | if (paddr < uv_hub_info->lowmem_remap_top) |
189f67c4 | 438 | paddr |= uv_hub_info->lowmem_remap_base; |
ad483005 MT |
439 | |
440 | if (m_val) { | |
441 | paddr |= uv_hub_info->gnode_upper; | |
c85375cd MT |
442 | paddr = ((paddr << uv_hub_info->m_shift) |
443 | >> uv_hub_info->m_shift) | | |
444 | ((paddr >> uv_hub_info->m_val) | |
445 | << uv_hub_info->n_lshift); | |
ad483005 | 446 | } else { |
c85375cd MT |
447 | paddr |= uv_soc_phys_ram_to_nasid(paddr) |
448 | << uv_hub_info->gpa_shift; | |
ad483005 | 449 | } |
6a469e46 | 450 | return paddr; |
9f5314fb JS |
451 | } |
452 | ||
9f5314fb JS |
453 | /* socket virtual --> UV global physical address */ |
454 | static inline unsigned long uv_gpa(void *v) | |
455 | { | |
189f67c4 | 456 | return uv_soc_phys_ram_to_gpa(__pa(v)); |
9f5314fb | 457 | } |
1d21e6e3 | 458 | |
fae419f2 RH |
459 | /* Top two bits indicate the requested address is in MMR space. */ |
460 | static inline int | |
461 | uv_gpa_in_mmr_space(unsigned long gpa) | |
462 | { | |
463 | return (gpa >> 62) == 0x3UL; | |
464 | } | |
465 | ||
729d69e6 RH |
466 | /* UV global physical address --> socket phys RAM */ |
467 | static inline unsigned long uv_gpa_to_soc_phys_ram(unsigned long gpa) | |
468 | { | |
5a51467b | 469 | unsigned long paddr; |
729d69e6 RH |
470 | unsigned long remap_base = uv_hub_info->lowmem_remap_base; |
471 | unsigned long remap_top = uv_hub_info->lowmem_remap_top; | |
c85375cd MT |
472 | unsigned int m_val = uv_hub_info->m_val; |
473 | ||
474 | if (m_val) | |
475 | gpa = ((gpa << uv_hub_info->m_shift) >> uv_hub_info->m_shift) | | |
476 | ((gpa >> uv_hub_info->n_lshift) << uv_hub_info->m_val); | |
729d69e6 | 477 | |
5a51467b | 478 | paddr = gpa & uv_hub_info->gpa_mask; |
729d69e6 RH |
479 | if (paddr >= remap_base && paddr < remap_base + remap_top) |
480 | paddr -= remap_base; | |
481 | return paddr; | |
482 | } | |
483 | ||
906f3b20 | 484 | /* gpa -> gnode */ |
1d21e6e3 RH |
485 | static inline unsigned long uv_gpa_to_gnode(unsigned long gpa) |
486 | { | |
c85375cd MT |
487 | unsigned int n_lshift = uv_hub_info->n_lshift; |
488 | ||
489 | if (n_lshift) | |
490 | return gpa >> n_lshift; | |
491 | ||
492 | return uv_gam_range(gpa)->nasid >> 1; | |
1d21e6e3 RH |
493 | } |
494 | ||
495 | /* gpa -> pnode */ | |
496 | static inline int uv_gpa_to_pnode(unsigned long gpa) | |
497 | { | |
906f3b20 | 498 | return uv_gpa_to_gnode(gpa) & uv_hub_info->pnode_mask; |
1d21e6e3 | 499 | } |
9f5314fb | 500 | |
906f3b20 | 501 | /* gpa -> node offset */ |
6a469e46 JS |
502 | static inline unsigned long uv_gpa_to_offset(unsigned long gpa) |
503 | { | |
c85375cd MT |
504 | unsigned int m_shift = uv_hub_info->m_shift; |
505 | ||
506 | if (m_shift) | |
507 | return (gpa << m_shift) >> m_shift; | |
508 | ||
509 | return (gpa & uv_hub_info->gpa_mask) - uv_gam_range_base(gpa); | |
6a469e46 JS |
510 | } |
511 | ||
c85375cd MT |
512 | /* Convert socket to node */ |
513 | static inline int _uv_socket_to_node(int socket, unsigned short *s2nid) | |
9f5314fb | 514 | { |
c85375cd | 515 | return s2nid ? s2nid[socket - uv_hub_info->min_socket] : socket; |
9f5314fb | 516 | } |
952cf6d7 | 517 | |
6e27b91c MT |
518 | static inline int uv_socket_to_node(int socket) |
519 | { | |
c85375cd MT |
520 | return _uv_socket_to_node(socket, uv_hub_info->socket_to_node); |
521 | } | |
6e27b91c | 522 | |
8c646cee SW |
523 | static inline int uv_pnode_to_socket(int pnode) |
524 | { | |
525 | unsigned short *p2s = uv_hub_info->pnode_to_socket; | |
526 | ||
527 | return p2s ? p2s[pnode - uv_hub_info->min_pnode] : pnode; | |
528 | } | |
529 | ||
c85375cd MT |
530 | /* pnode, offset --> socket virtual */ |
531 | static inline void *uv_pnode_offset_to_vaddr(int pnode, unsigned long offset) | |
532 | { | |
533 | unsigned int m_val = uv_hub_info->m_val; | |
534 | unsigned long base; | |
8a50c585 | 535 | unsigned short sockid; |
c85375cd MT |
536 | |
537 | if (m_val) | |
538 | return __va(((unsigned long)pnode << m_val) | offset); | |
539 | ||
8c646cee | 540 | sockid = uv_pnode_to_socket(pnode); |
c85375cd MT |
541 | |
542 | /* limit address of previous socket is our base, except node 0 is 0 */ | |
8a50c585 | 543 | if (sockid == 0) |
c85375cd MT |
544 | return __va((unsigned long)offset); |
545 | ||
8a50c585 | 546 | base = (unsigned long)(uv_hub_info->gr_table[sockid - 1].limit); |
c85375cd | 547 | return __va(base << UV_GAM_RANGE_SHFT | offset); |
6e27b91c MT |
548 | } |
549 | ||
550 | /* Extract/Convert a PNODE from an APICID (full apicid, not processor subset) */ | |
9f5314fb | 551 | static inline int uv_apicid_to_pnode(int apicid) |
952cf6d7 | 552 | { |
6e27b91c MT |
553 | int pnode = apicid >> uv_hub_info->apic_pnode_shift; |
554 | unsigned short *s2pn = uv_hub_info->socket_to_pnode; | |
555 | ||
556 | return s2pn ? s2pn[pnode - uv_hub_info->min_socket] : pnode; | |
952cf6d7 JS |
557 | } |
558 | ||
559 | /* | |
560 | * Access global MMRs using the low memory MMR32 space. This region supports | |
561 | * faster MMR access but not all MMRs are accessible in this space. | |
562 | */ | |
39d30770 | 563 | static inline unsigned long *uv_global_mmr32_address(int pnode, unsigned long offset) |
952cf6d7 JS |
564 | { |
565 | return __va(UV_GLOBAL_MMR32_BASE | | |
9f5314fb | 566 | UV_GLOBAL_MMR32_PNODE_BITS(pnode) | offset); |
952cf6d7 JS |
567 | } |
568 | ||
39d30770 | 569 | static inline void uv_write_global_mmr32(int pnode, unsigned long offset, unsigned long val) |
952cf6d7 | 570 | { |
8dc579e8 | 571 | writeq(val, uv_global_mmr32_address(pnode, offset)); |
952cf6d7 JS |
572 | } |
573 | ||
39d30770 | 574 | static inline unsigned long uv_read_global_mmr32(int pnode, unsigned long offset) |
952cf6d7 | 575 | { |
8dc579e8 | 576 | return readq(uv_global_mmr32_address(pnode, offset)); |
952cf6d7 JS |
577 | } |
578 | ||
579 | /* | |
580 | * Access Global MMR space using the MMR space located at the top of physical | |
581 | * memory. | |
582 | */ | |
a289cc7c | 583 | static inline volatile void __iomem *uv_global_mmr64_address(int pnode, unsigned long offset) |
952cf6d7 JS |
584 | { |
585 | return __va(UV_GLOBAL_MMR64_BASE | | |
9f5314fb | 586 | UV_GLOBAL_MMR64_PNODE_BITS(pnode) | offset); |
952cf6d7 JS |
587 | } |
588 | ||
39d30770 | 589 | static inline void uv_write_global_mmr64(int pnode, unsigned long offset, unsigned long val) |
952cf6d7 | 590 | { |
8dc579e8 | 591 | writeq(val, uv_global_mmr64_address(pnode, offset)); |
952cf6d7 JS |
592 | } |
593 | ||
39d30770 | 594 | static inline unsigned long uv_read_global_mmr64(int pnode, unsigned long offset) |
952cf6d7 | 595 | { |
8dc579e8 | 596 | return readq(uv_global_mmr64_address(pnode, offset)); |
952cf6d7 JS |
597 | } |
598 | ||
39d30770 MT |
599 | static inline void uv_write_global_mmr8(int pnode, unsigned long offset, unsigned char val) |
600 | { | |
601 | writeb(val, uv_global_mmr64_address(pnode, offset)); | |
602 | } | |
603 | ||
604 | static inline unsigned char uv_read_global_mmr8(int pnode, unsigned long offset) | |
605 | { | |
606 | return readb(uv_global_mmr64_address(pnode, offset)); | |
607 | } | |
608 | ||
952cf6d7 | 609 | /* |
9f5314fb | 610 | * Access hub local MMRs. Faster than using global space but only local MMRs |
952cf6d7 JS |
611 | * are accessible. |
612 | */ | |
613 | static inline unsigned long *uv_local_mmr_address(unsigned long offset) | |
614 | { | |
615 | return __va(UV_LOCAL_MMR_BASE | offset); | |
616 | } | |
617 | ||
618 | static inline unsigned long uv_read_local_mmr(unsigned long offset) | |
619 | { | |
8dc579e8 | 620 | return readq(uv_local_mmr_address(offset)); |
952cf6d7 JS |
621 | } |
622 | ||
623 | static inline void uv_write_local_mmr(unsigned long offset, unsigned long val) | |
624 | { | |
8dc579e8 | 625 | writeq(val, uv_local_mmr_address(offset)); |
952cf6d7 JS |
626 | } |
627 | ||
7f1baa06 MT |
628 | static inline unsigned char uv_read_local_mmr8(unsigned long offset) |
629 | { | |
8dc579e8 | 630 | return readb(uv_local_mmr_address(offset)); |
7f1baa06 MT |
631 | } |
632 | ||
633 | static inline void uv_write_local_mmr8(unsigned long offset, unsigned char val) | |
634 | { | |
8dc579e8 | 635 | writeb(val, uv_local_mmr_address(offset)); |
7f1baa06 MT |
636 | } |
637 | ||
8400def8 JS |
638 | /* Blade-local cpu number of current cpu. Numbered 0 .. <# cpus on the blade> */ |
639 | static inline int uv_blade_processor_id(void) | |
640 | { | |
5627a825 | 641 | return uv_cpu_info->blade_cpu_id; |
8400def8 JS |
642 | } |
643 | ||
5627a825 MT |
644 | /* Blade-local cpu number of cpu N. Numbered 0 .. <# cpus on the blade> */ |
645 | static inline int uv_cpu_blade_processor_id(int cpu) | |
646 | { | |
647 | return uv_cpu_info_per(cpu)->blade_cpu_id; | |
648 | } | |
5627a825 | 649 | |
9b9ee172 | 650 | /* Blade number to Node number (UV2..UV4 is 1:1) */ |
906f3b20 MT |
651 | static inline int uv_blade_to_node(int blade) |
652 | { | |
8a50c585 | 653 | return uv_socket_to_node(blade); |
906f3b20 MT |
654 | } |
655 | ||
54aa699e | 656 | /* Blade number of current cpu. Numbered 0 .. <#blades -1> */ |
8400def8 JS |
657 | static inline int uv_numa_blade_id(void) |
658 | { | |
659 | return uv_hub_info->numa_blade_id; | |
660 | } | |
661 | ||
906f3b20 MT |
662 | /* |
663 | * Convert linux node number to the UV blade number. | |
9b9ee172 | 664 | * .. Currently for UV2 thru UV4 the node and the blade are identical. |
8a50c585 | 665 | * .. UV5 needs conversion when sub-numa clustering is enabled. |
906f3b20 MT |
666 | */ |
667 | static inline int uv_node_to_blade_id(int nid) | |
8400def8 | 668 | { |
8a50c585 SW |
669 | unsigned short *n2s = uv_hub_info->node_to_socket; |
670 | ||
671 | return n2s ? n2s[nid] : nid; | |
8400def8 JS |
672 | } |
673 | ||
de0038bf | 674 | /* Convert a CPU number to the UV blade number */ |
906f3b20 | 675 | static inline int uv_cpu_to_blade_id(int cpu) |
8400def8 | 676 | { |
8a50c585 | 677 | return uv_cpu_hub_info(cpu)->numa_blade_id; |
8400def8 JS |
678 | } |
679 | ||
9f5314fb JS |
680 | /* Convert a blade id to the PNODE of the blade */ |
681 | static inline int uv_blade_to_pnode(int bid) | |
8400def8 | 682 | { |
8a50c585 SW |
683 | unsigned short *s2p = uv_hub_info->socket_to_pnode; |
684 | ||
685 | return s2p ? s2p[bid] : bid; | |
8400def8 JS |
686 | } |
687 | ||
6c7184b7 JS |
688 | /* Nid of memory node on blade. -1 if no blade-local memory */ |
689 | static inline int uv_blade_to_memory_nid(int bid) | |
690 | { | |
906f3b20 | 691 | return uv_hub_info_list(uv_blade_to_node(bid))->memory_nid; |
6c7184b7 JS |
692 | } |
693 | ||
8400def8 JS |
694 | /* Determine the number of possible cpus on a blade */ |
695 | static inline int uv_blade_nr_possible_cpus(int bid) | |
696 | { | |
906f3b20 | 697 | return uv_hub_info_list(uv_blade_to_node(bid))->nr_possible_cpus; |
8400def8 JS |
698 | } |
699 | ||
700 | /* Determine the number of online cpus on a blade */ | |
701 | static inline int uv_blade_nr_online_cpus(int bid) | |
702 | { | |
906f3b20 | 703 | return uv_hub_info_list(uv_blade_to_node(bid))->nr_online_cpus; |
8400def8 JS |
704 | } |
705 | ||
9f5314fb JS |
706 | /* Convert a cpu id to the PNODE of the blade containing the cpu */ |
707 | static inline int uv_cpu_to_pnode(int cpu) | |
8400def8 | 708 | { |
906f3b20 | 709 | return uv_cpu_hub_info(cpu)->pnode; |
8400def8 JS |
710 | } |
711 | ||
9f5314fb JS |
712 | /* Convert a linux node number to the PNODE of the blade */ |
713 | static inline int uv_node_to_pnode(int nid) | |
8400def8 | 714 | { |
906f3b20 | 715 | return uv_hub_info_list(nid)->pnode; |
8400def8 JS |
716 | } |
717 | ||
718 | /* Maximum possible number of blades */ | |
906f3b20 | 719 | extern short uv_possible_blades; |
8400def8 JS |
720 | static inline int uv_num_possible_blades(void) |
721 | { | |
722 | return uv_possible_blades; | |
723 | } | |
724 | ||
0d12ef0c MT |
725 | /* Per Hub NMI support */ |
726 | extern void uv_nmi_setup(void); | |
abdf1df6 | 727 | extern void uv_nmi_setup_hubless(void); |
0d12ef0c | 728 | |
97d21003 | 729 | /* BIOS/Kernel flags exchange MMR */ |
730 | #define UVH_BIOS_KERNEL_MMR UVH_SCRATCH5 | |
731 | #define UVH_BIOS_KERNEL_MMR_ALIAS UVH_SCRATCH5_ALIAS | |
732 | #define UVH_BIOS_KERNEL_MMR_ALIAS_2 UVH_SCRATCH5_ALIAS_2 | |
733 | ||
734 | /* TSC sync valid, set by BIOS */ | |
735 | #define UVH_TSC_SYNC_MMR UVH_BIOS_KERNEL_MMR | |
736 | #define UVH_TSC_SYNC_SHIFT 10 | |
737 | #define UVH_TSC_SYNC_SHIFT_UV2K 16 /* UV2/3k have different bits */ | |
738 | #define UVH_TSC_SYNC_MASK 3 /* 0011 */ | |
739 | #define UVH_TSC_SYNC_VALID 3 /* 0011 */ | |
6a7cf55e | 740 | #define UVH_TSC_SYNC_UNKNOWN 0 /* 0000 */ |
97d21003 | 741 | |
0d12ef0c | 742 | /* BMC sets a bit this MMR non-zero before sending an NMI */ |
97d21003 | 743 | #define UVH_NMI_MMR UVH_BIOS_KERNEL_MMR |
744 | #define UVH_NMI_MMR_CLEAR UVH_BIOS_KERNEL_MMR_ALIAS | |
0d12ef0c | 745 | #define UVH_NMI_MMR_SHIFT 63 |
97d21003 | 746 | #define UVH_NMI_MMR_TYPE "SCRATCH5" |
0d12ef0c | 747 | |
0d12ef0c MT |
748 | struct uv_hub_nmi_s { |
749 | raw_spinlock_t nmi_lock; | |
750 | atomic_t in_nmi; /* flag this node in UV NMI IRQ */ | |
751 | atomic_t cpu_owner; /* last locker of this struct */ | |
752 | atomic_t read_mmr_count; /* count of MMR reads */ | |
753 | atomic_t nmi_count; /* count of true UV NMIs */ | |
754 | unsigned long nmi_value; /* last value read from NMI MMR */ | |
abdf1df6 | 755 | bool hub_present; /* false means UV hubless system */ |
756 | bool pch_owner; /* indicates this hub owns PCH */ | |
0d12ef0c MT |
757 | }; |
758 | ||
759 | struct uv_cpu_nmi_s { | |
760 | struct uv_hub_nmi_s *hub; | |
e1632170 CL |
761 | int state; |
762 | int pinging; | |
0d12ef0c MT |
763 | int queries; |
764 | int pings; | |
765 | }; | |
766 | ||
e1632170 CL |
767 | DECLARE_PER_CPU(struct uv_cpu_nmi_s, uv_cpu_nmi); |
768 | ||
7c52198b | 769 | #define uv_hub_nmi this_cpu_read(uv_cpu_nmi.hub) |
e1632170 | 770 | #define uv_cpu_nmi_per(cpu) (per_cpu(uv_cpu_nmi, cpu)) |
0d12ef0c MT |
771 | #define uv_hub_nmi_per(cpu) (uv_cpu_nmi_per(cpu).hub) |
772 | ||
773 | /* uv_cpu_nmi_states */ | |
774 | #define UV_NMI_STATE_OUT 0 | |
775 | #define UV_NMI_STATE_IN 1 | |
776 | #define UV_NMI_STATE_DUMP 2 | |
777 | #define UV_NMI_STATE_DUMP_DONE 3 | |
778 | ||
7a1110e8 JS |
779 | /* |
780 | * Get the minimum revision number of the hub chips within the partition. | |
eb1e3461 | 781 | * (See UVx_HUB_REVISION_BASE above for specific values.) |
7a1110e8 JS |
782 | */ |
783 | static inline int uv_get_min_hub_revision_id(void) | |
784 | { | |
2a919596 | 785 | return uv_hub_info->hub_revision; |
7a1110e8 JS |
786 | } |
787 | ||
bc5d9940 | 788 | #endif /* CONFIG_X86_64 */ |
7f1baa06 | 789 | #endif /* _ASM_X86_UV_UV_HUB_H */ |