summaryrefslogtreecommitdiffstats
path: root/include/asm-x86/uv/uv_hub.h
blob: b4fcf9cf8951618d636a20cecab447b08db198c5 (plain)
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
/*
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * SGI UV architectural definitions
 *
 * Copyright (C) 2007 Silicon Graphics, Inc. All rights reserved.
 */

#ifndef __ASM_X86_UV_HUB_H__
#define __ASM_X86_UV_HUB_H__

#include <linux/numa.h>
#include <linux/percpu.h>
#include <asm/types.h>
#include <asm/percpu.h>


/*
 * Addressing Terminology
 *
 * 	NASID - network ID of a router, Mbrick or Cbrick. Nasid values of
 * 		routers always have low bit of 1, C/MBricks have low bit
 * 		equal to 0. Most addressing macros that target UV hub chips
 * 		right shift the NASID by 1 to exclude the always-zero bit.
 *
 *	SNASID - NASID right shifted by 1 bit.
 *
 *
 *  Memory/UV-HUB Processor Socket Address Format:
 *  +--------+---------------+---------------------+
 *  |00..0000|    SNASID     |      NodeOffset     |
 *  +--------+---------------+---------------------+
 *           <--- N bits --->|<--------M bits ----->
 *
 *	M number of node offset bits (35 .. 40)
 *	N number of SNASID bits (0 .. 10)
 *
 *		Note: M + N cannot currently exceed 44 (x86_64) or 46 (IA64).
 *		The actual values are configuration dependent and are set at
 *		boot time
 *
 * APICID format
 * 	NOTE!!!!!! This is the current format of the APICID. However, code
 * 	should assume that this will change in the future. Use functions
 * 	in this file for all APICID bit manipulations and conversion.
 *
 * 		1111110000000000
 * 		5432109876543210
 *		nnnnnnnnnnlc0cch
 *		sssssssssss
 *
 *			n  = snasid bits
 *			l =  socket number on board
 *			c  = core
 *			h  = hyperthread
 *			s  = bits that are in the socket CSR
 *
 *	Note: Processor only supports 12 bits in the APICID register. The ACPI
 *	      tables hold all 16 bits. Software needs to be aware of this.
 *
 * 	      Unless otherwise specified, all references to APICID refer to
 * 	      the FULL value contained in ACPI tables, not the subset in the
 * 	      processor APICID register.
 */


/*
 * Maximum number of bricks in all partitions and in all coherency domains.
 * This is the total number of bricks accessible in the numalink fabric. It
 * includes all C & M bricks. Routers are NOT included.
 *
 * This value is also the value of the maximum number of non-router NASIDs
 * in the numalink fabric.
 *
 * NOTE: a brick may be 1 or 2 OS nodes. Don't get these confused.
 */
#define UV_MAX_NUMALINK_BLADES	16384

/*
 * Maximum number of C/Mbricks within a software SSI (hardware may support
 * more).
 */
#define UV_MAX_SSI_BLADES	256

/*
 * The largest possible NASID of a C or M brick (+ 2)
 */
#define UV_MAX_NASID_VALUE	(UV_MAX_NUMALINK_NODES * 2)

/*
 * The following defines attributes of the HUB chip. These attributes are
 * frequently referenced and are kept in the per-cpu data areas of each cpu.
 * They are kept together in a struct to minimize cache misses.
 */
struct uv_hub_info_s {
	unsigned long	global_mmr_base;
	unsigned short	local_nasid;
	unsigned short	gnode_upper;
	unsigned short	coherency_domain_number;
	unsigned short	numa_blade_id;
	unsigned char	blade_processor_id;
	unsigned char	m_val;
	unsigned char	n_val;
};
DECLARE_PER_CPU(struct uv_hub_info_s, __uv_hub_info);
#define uv_hub_info 		(&__get_cpu_var(__uv_hub_info))
#define uv_cpu_hub_info(cpu)	(&per_cpu(__uv_hub_info, cpu))

/*
 * Local & Global MMR space macros.
 * 	Note: macros are intended to be used ONLY by inline functions
 * 	in this file - not by other kernel code.
 */
#define UV_SNASID(n)			((n) >> 1)
#define UV_NASID(n)			((n) << 1)

#define UV_LOCAL_MMR_BASE		0xf4000000UL
#define UV_GLOBAL_MMR32_BASE		0xf8000000UL
#define UV_GLOBAL_MMR64_BASE		(uv_hub_info->global_mmr_base)

#define UV_GLOBAL_MMR32_SNASID_MASK	0x3ff
#define UV_GLOBAL_MMR32_SNASID_SHIFT	15
#define UV_GLOBAL_MMR64_SNASID_SHIFT	26

#define UV_GLOBAL_MMR32_NASID_BITS(n)					\
		(((UV_SNASID(n) & UV_GLOBAL_MMR32_SNASID_MASK)) <<	\
		(UV_GLOBAL_MMR32_SNASID_SHIFT))

#define UV_GLOBAL_MMR64_NASID_BITS(n)					\
	((unsigned long)UV_SNASID(n) << UV_GLOBAL_MMR64_SNASID_SHIFT)

#define UV_APIC_NASID_SHIFT	6

/*
 * Extract a NASID from an APICID (full apicid, not processor subset)
 */
static inline int uv_apicid_to_nasid(int apicid)
{
	return (UV_NASID(apicid >> UV_APIC_NASID_SHIFT));
}

/*
 * Access global MMRs using the low memory MMR32 space. This region supports
 * faster MMR access but not all MMRs are accessible in this space.
 */
static inline unsigned long *uv_global_mmr32_address(int nasid,
				unsigned long offset)
{
	return __va(UV_GLOBAL_MMR32_BASE |
		       UV_GLOBAL_MMR32_NASID_BITS(nasid) | offset);
}

static inline void uv_write_global_mmr32(int nasid, unsigned long offset,
				 unsigned long val)
{
	*uv_global_mmr32_address(nasid, offset) = val;
}

static inline unsigned long uv_read_global_mmr32(int nasid,
						 unsigned long offset)
{
	return *uv_global_mmr32_address(nasid, offset);
}

/*
 * Access Global MMR space using the MMR space located at the top of physical
 * memory.
 */
static inline unsigned long *uv_global_mmr64_address(int nasid,
				unsigned long offset)
{
	return __va(UV_GLOBAL_MMR64_BASE |
		       UV_GLOBAL_MMR64_NASID_BITS(nasid) | offset);
}

static inline void uv_write_global_mmr64(int nasid, unsigned long offset,
				unsigned long val)
{
	*uv_global_mmr64_address(nasid, offset) = val;
}

static inline unsigned long uv_read_global_mmr64(int nasid,
						 unsigned long offset)
{
	return *uv_global_mmr64_address(nasid, offset);
}

/*
 * Access node local MMRs. Faster than using global space but only local MMRs
 * are accessible.
 */
static inline unsigned long *uv_local_mmr_address(unsigned long offset)
{
	return __va(UV_LOCAL_MMR_BASE | offset);
}

static inline unsigned long uv_read_local_mmr(unsigned long offset)
{
	return *uv_local_mmr_address(offset);
}

static inline void uv_write_local_mmr(unsigned long offset, unsigned long val)
{
	*uv_local_mmr_address(offset) = val;
}

#endif /* __ASM_X86_UV_HUB__ */