diff options
author | Jack Steiner <steiner@sgi.com> | 2008-05-28 10:51:18 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-06-02 06:56:00 -0400 |
commit | 9f5314fb4d556d3132c784d0df47352b2830ca53 (patch) | |
tree | c66945d21aab945f33498d8d146596b5d9e3a6e4 /arch/x86/kernel/genx2apic_uv_x.c | |
parent | c46e62f73569d7ef42255bd6f31e35925b7f1492 (diff) |
x86, uv: update macros used by UV platform
Update the UV address macros to better describe the
fields of UV physical addresses. Improve comments
in the header files. Add additional MMR definitions.
Signed-off-by: Jack Steiner <steiner@sgi.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/genx2apic_uv_x.c')
-rw-r--r-- | arch/x86/kernel/genx2apic_uv_x.c | 141 |
1 files changed, 98 insertions, 43 deletions
diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index ebf13908a743..45e84acca8a9 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * | 5 | * |
6 | * SGI UV APIC functions (note: not an Intel compatible APIC) | 6 | * SGI UV APIC functions (note: not an Intel compatible APIC) |
7 | * | 7 | * |
8 | * Copyright (C) 2007 Silicon Graphics, Inc. All rights reserved. | 8 | * Copyright (C) 2007-2008 Silicon Graphics, Inc. All rights reserved. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/threads.h> | 11 | #include <linux/threads.h> |
@@ -55,37 +55,37 @@ static cpumask_t uv_vector_allocation_domain(int cpu) | |||
55 | int uv_wakeup_secondary(int phys_apicid, unsigned int start_rip) | 55 | int uv_wakeup_secondary(int phys_apicid, unsigned int start_rip) |
56 | { | 56 | { |
57 | unsigned long val; | 57 | unsigned long val; |
58 | int nasid; | 58 | int pnode; |
59 | 59 | ||
60 | nasid = uv_apicid_to_nasid(phys_apicid); | 60 | pnode = uv_apicid_to_pnode(phys_apicid); |
61 | val = (1UL << UVH_IPI_INT_SEND_SHFT) | | 61 | val = (1UL << UVH_IPI_INT_SEND_SHFT) | |
62 | (phys_apicid << UVH_IPI_INT_APIC_ID_SHFT) | | 62 | (phys_apicid << UVH_IPI_INT_APIC_ID_SHFT) | |
63 | (((long)start_rip << UVH_IPI_INT_VECTOR_SHFT) >> 12) | | 63 | (((long)start_rip << UVH_IPI_INT_VECTOR_SHFT) >> 12) | |
64 | APIC_DM_INIT; | 64 | APIC_DM_INIT; |
65 | uv_write_global_mmr64(nasid, UVH_IPI_INT, val); | 65 | uv_write_global_mmr64(pnode, UVH_IPI_INT, val); |
66 | mdelay(10); | 66 | mdelay(10); |
67 | 67 | ||
68 | val = (1UL << UVH_IPI_INT_SEND_SHFT) | | 68 | val = (1UL << UVH_IPI_INT_SEND_SHFT) | |
69 | (phys_apicid << UVH_IPI_INT_APIC_ID_SHFT) | | 69 | (phys_apicid << UVH_IPI_INT_APIC_ID_SHFT) | |
70 | (((long)start_rip << UVH_IPI_INT_VECTOR_SHFT) >> 12) | | 70 | (((long)start_rip << UVH_IPI_INT_VECTOR_SHFT) >> 12) | |
71 | APIC_DM_STARTUP; | 71 | APIC_DM_STARTUP; |
72 | uv_write_global_mmr64(nasid, UVH_IPI_INT, val); | 72 | uv_write_global_mmr64(pnode, UVH_IPI_INT, val); |
73 | return 0; | 73 | return 0; |
74 | } | 74 | } |
75 | 75 | ||
76 | static void uv_send_IPI_one(int cpu, int vector) | 76 | static void uv_send_IPI_one(int cpu, int vector) |
77 | { | 77 | { |
78 | unsigned long val, apicid, lapicid; | 78 | unsigned long val, apicid, lapicid; |
79 | int nasid; | 79 | int pnode; |
80 | 80 | ||
81 | apicid = per_cpu(x86_cpu_to_apicid, cpu); /* ZZZ - cache node-local ? */ | 81 | apicid = per_cpu(x86_cpu_to_apicid, cpu); /* ZZZ - cache node-local ? */ |
82 | lapicid = apicid & 0x3f; /* ZZZ macro needed */ | 82 | lapicid = apicid & 0x3f; /* ZZZ macro needed */ |
83 | nasid = uv_apicid_to_nasid(apicid); | 83 | pnode = uv_apicid_to_pnode(apicid); |
84 | val = | 84 | val = |
85 | (1UL << UVH_IPI_INT_SEND_SHFT) | (lapicid << | 85 | (1UL << UVH_IPI_INT_SEND_SHFT) | (lapicid << |
86 | UVH_IPI_INT_APIC_ID_SHFT) | | 86 | UVH_IPI_INT_APIC_ID_SHFT) | |
87 | (vector << UVH_IPI_INT_VECTOR_SHFT); | 87 | (vector << UVH_IPI_INT_VECTOR_SHFT); |
88 | uv_write_global_mmr64(nasid, UVH_IPI_INT, val); | 88 | uv_write_global_mmr64(pnode, UVH_IPI_INT, val); |
89 | } | 89 | } |
90 | 90 | ||
91 | static void uv_send_IPI_mask(cpumask_t mask, int vector) | 91 | static void uv_send_IPI_mask(cpumask_t mask, int vector) |
@@ -159,39 +159,81 @@ struct genapic apic_x2apic_uv_x = { | |||
159 | .phys_pkg_id = phys_pkg_id, /* Fixme ZZZ */ | 159 | .phys_pkg_id = phys_pkg_id, /* Fixme ZZZ */ |
160 | }; | 160 | }; |
161 | 161 | ||
162 | static __cpuinit void set_x2apic_extra_bits(int nasid) | 162 | static __cpuinit void set_x2apic_extra_bits(int pnode) |
163 | { | 163 | { |
164 | __get_cpu_var(x2apic_extra_bits) = ((nasid >> 1) << 6); | 164 | __get_cpu_var(x2apic_extra_bits) = (pnode << 6); |
165 | } | 165 | } |
166 | 166 | ||
167 | /* | 167 | /* |
168 | * Called on boot cpu. | 168 | * Called on boot cpu. |
169 | */ | 169 | */ |
170 | static __init int boot_pnode_to_blade(int pnode) | ||
171 | { | ||
172 | int blade; | ||
173 | |||
174 | for (blade = 0; blade < uv_num_possible_blades(); blade++) | ||
175 | if (pnode == uv_blade_info[blade].pnode) | ||
176 | return blade; | ||
177 | BUG(); | ||
178 | } | ||
179 | |||
180 | struct redir_addr { | ||
181 | unsigned long redirect; | ||
182 | unsigned long alias; | ||
183 | }; | ||
184 | |||
185 | #define DEST_SHIFT UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR_DEST_BASE_SHFT | ||
186 | |||
187 | static __initdata struct redir_addr redir_addrs[] = { | ||
188 | {UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR, UVH_SI_ALIAS0_OVERLAY_CONFIG}, | ||
189 | {UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR, UVH_SI_ALIAS1_OVERLAY_CONFIG}, | ||
190 | {UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR, UVH_SI_ALIAS2_OVERLAY_CONFIG}, | ||
191 | }; | ||
192 | |||
193 | static __init void get_lowmem_redirect(unsigned long *base, unsigned long *size) | ||
194 | { | ||
195 | union uvh_si_alias0_overlay_config_u alias; | ||
196 | union uvh_rh_gam_alias210_redirect_config_2_mmr_u redirect; | ||
197 | int i; | ||
198 | |||
199 | for (i = 0; i < ARRAY_SIZE(redir_addrs); i++) { | ||
200 | alias.v = uv_read_local_mmr(redir_addrs[i].alias); | ||
201 | if (alias.s.base == 0) { | ||
202 | *size = (1UL << alias.s.m_alias); | ||
203 | redirect.v = uv_read_local_mmr(redir_addrs[i].redirect); | ||
204 | *base = (unsigned long)redirect.s.dest_base << DEST_SHIFT; | ||
205 | return; | ||
206 | } | ||
207 | } | ||
208 | BUG(); | ||
209 | } | ||
210 | |||
170 | static __init void uv_system_init(void) | 211 | static __init void uv_system_init(void) |
171 | { | 212 | { |
172 | union uvh_si_addr_map_config_u m_n_config; | 213 | union uvh_si_addr_map_config_u m_n_config; |
173 | int bytes, nid, cpu, lcpu, nasid, last_nasid, blade; | 214 | union uvh_node_id_u node_id; |
174 | unsigned long mmr_base; | 215 | unsigned long gnode_upper, lowmem_redir_base, lowmem_redir_size; |
216 | int bytes, nid, cpu, lcpu, pnode, blade, i, j, m_val, n_val; | ||
217 | unsigned long mmr_base, present; | ||
175 | 218 | ||
176 | m_n_config.v = uv_read_local_mmr(UVH_SI_ADDR_MAP_CONFIG); | 219 | m_n_config.v = uv_read_local_mmr(UVH_SI_ADDR_MAP_CONFIG); |
220 | m_val = m_n_config.s.m_skt; | ||
221 | n_val = m_n_config.s.n_skt; | ||
177 | mmr_base = | 222 | mmr_base = |
178 | uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR) & | 223 | uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR) & |
179 | ~UV_MMR_ENABLE; | 224 | ~UV_MMR_ENABLE; |
180 | printk(KERN_DEBUG "UV: global MMR base 0x%lx\n", mmr_base); | 225 | printk(KERN_DEBUG "UV: global MMR base 0x%lx\n", mmr_base); |
181 | 226 | ||
182 | last_nasid = -1; | 227 | for(i = 0; i < UVH_NODE_PRESENT_TABLE_DEPTH; i++) |
183 | for_each_possible_cpu(cpu) { | 228 | uv_possible_blades += |
184 | nid = cpu_to_node(cpu); | 229 | hweight64(uv_read_local_mmr( UVH_NODE_PRESENT_TABLE + i * 8)); |
185 | nasid = uv_apicid_to_nasid(per_cpu(x86_cpu_to_apicid, cpu)); | ||
186 | if (nasid != last_nasid) | ||
187 | uv_possible_blades++; | ||
188 | last_nasid = nasid; | ||
189 | } | ||
190 | printk(KERN_DEBUG "UV: Found %d blades\n", uv_num_possible_blades()); | 230 | printk(KERN_DEBUG "UV: Found %d blades\n", uv_num_possible_blades()); |
191 | 231 | ||
192 | bytes = sizeof(struct uv_blade_info) * uv_num_possible_blades(); | 232 | bytes = sizeof(struct uv_blade_info) * uv_num_possible_blades(); |
193 | uv_blade_info = alloc_bootmem_pages(bytes); | 233 | uv_blade_info = alloc_bootmem_pages(bytes); |
194 | 234 | ||
235 | get_lowmem_redirect(&lowmem_redir_base, &lowmem_redir_size); | ||
236 | |||
195 | bytes = sizeof(uv_node_to_blade[0]) * num_possible_nodes(); | 237 | bytes = sizeof(uv_node_to_blade[0]) * num_possible_nodes(); |
196 | uv_node_to_blade = alloc_bootmem_pages(bytes); | 238 | uv_node_to_blade = alloc_bootmem_pages(bytes); |
197 | memset(uv_node_to_blade, 255, bytes); | 239 | memset(uv_node_to_blade, 255, bytes); |
@@ -200,43 +242,56 @@ static __init void uv_system_init(void) | |||
200 | uv_cpu_to_blade = alloc_bootmem_pages(bytes); | 242 | uv_cpu_to_blade = alloc_bootmem_pages(bytes); |
201 | memset(uv_cpu_to_blade, 255, bytes); | 243 | memset(uv_cpu_to_blade, 255, bytes); |
202 | 244 | ||
203 | last_nasid = -1; | 245 | blade = 0; |
204 | blade = -1; | 246 | for (i = 0; i < UVH_NODE_PRESENT_TABLE_DEPTH; i++) { |
205 | lcpu = -1; | 247 | present = uv_read_local_mmr(UVH_NODE_PRESENT_TABLE + i * 8); |
206 | for_each_possible_cpu(cpu) { | 248 | for (j = 0; j < 64; j++) { |
207 | nid = cpu_to_node(cpu); | 249 | if (!test_bit(j, &present)) |
208 | nasid = uv_apicid_to_nasid(per_cpu(x86_cpu_to_apicid, cpu)); | 250 | continue; |
209 | if (nasid != last_nasid) { | 251 | uv_blade_info[blade].pnode = (i * 64 + j); |
210 | blade++; | 252 | uv_blade_info[blade].nr_possible_cpus = 0; |
211 | lcpu = -1; | ||
212 | uv_blade_info[blade].nr_posible_cpus = 0; | ||
213 | uv_blade_info[blade].nr_online_cpus = 0; | 253 | uv_blade_info[blade].nr_online_cpus = 0; |
254 | blade++; | ||
214 | } | 255 | } |
215 | last_nasid = nasid; | 256 | } |
216 | lcpu++; | ||
217 | 257 | ||
218 | uv_cpu_hub_info(cpu)->m_val = m_n_config.s.m_skt; | 258 | node_id.v = uv_read_local_mmr(UVH_NODE_ID); |
219 | uv_cpu_hub_info(cpu)->n_val = m_n_config.s.n_skt; | 259 | gnode_upper = (((unsigned long)node_id.s.node_id) & |
260 | ~((1 << n_val) - 1)) << m_val; | ||
261 | |||
262 | for_each_present_cpu(cpu) { | ||
263 | nid = cpu_to_node(cpu); | ||
264 | pnode = uv_apicid_to_pnode(per_cpu(x86_cpu_to_apicid, cpu)); | ||
265 | blade = boot_pnode_to_blade(pnode); | ||
266 | lcpu = uv_blade_info[blade].nr_possible_cpus; | ||
267 | uv_blade_info[blade].nr_possible_cpus++; | ||
268 | |||
269 | uv_cpu_hub_info(cpu)->lowmem_remap_base = lowmem_redir_base; | ||
270 | uv_cpu_hub_info(cpu)->lowmem_remap_top = | ||
271 | lowmem_redir_base + lowmem_redir_size; | ||
272 | uv_cpu_hub_info(cpu)->m_val = m_val; | ||
273 | uv_cpu_hub_info(cpu)->n_val = m_val; | ||
220 | uv_cpu_hub_info(cpu)->numa_blade_id = blade; | 274 | uv_cpu_hub_info(cpu)->numa_blade_id = blade; |
221 | uv_cpu_hub_info(cpu)->blade_processor_id = lcpu; | 275 | uv_cpu_hub_info(cpu)->blade_processor_id = lcpu; |
222 | uv_cpu_hub_info(cpu)->local_nasid = nasid; | 276 | uv_cpu_hub_info(cpu)->pnode = pnode; |
223 | uv_cpu_hub_info(cpu)->gnode_upper = | 277 | uv_cpu_hub_info(cpu)->pnode_mask = (1 << n_val) - 1; |
224 | nasid & ~((1 << uv_hub_info->n_val) - 1); | 278 | uv_cpu_hub_info(cpu)->gpa_mask = (1 << (m_val + n_val)) - 1; |
279 | uv_cpu_hub_info(cpu)->gnode_upper = gnode_upper; | ||
225 | uv_cpu_hub_info(cpu)->global_mmr_base = mmr_base; | 280 | uv_cpu_hub_info(cpu)->global_mmr_base = mmr_base; |
226 | uv_cpu_hub_info(cpu)->coherency_domain_number = 0;/* ZZZ */ | 281 | uv_cpu_hub_info(cpu)->coherency_domain_number = 0;/* ZZZ */ |
227 | uv_blade_info[blade].nasid = nasid; | ||
228 | uv_blade_info[blade].nr_posible_cpus++; | ||
229 | uv_node_to_blade[nid] = blade; | 282 | uv_node_to_blade[nid] = blade; |
230 | uv_cpu_to_blade[cpu] = blade; | 283 | uv_cpu_to_blade[cpu] = blade; |
231 | 284 | ||
232 | printk(KERN_DEBUG "UV cpu %d, apicid 0x%x, nasid %d, nid %d\n", | 285 | printk(KERN_DEBUG "UV cpu %d, apicid 0x%x, pnode %d, nid %d, " |
233 | cpu, per_cpu(x86_cpu_to_apicid, cpu), nasid, nid); | 286 | "lcpu %d, blade %d\n", |
234 | printk(KERN_DEBUG "UV lcpu %d, blade %d\n", lcpu, blade); | 287 | cpu, per_cpu(x86_cpu_to_apicid, cpu), pnode, nid, |
288 | lcpu, blade); | ||
235 | } | 289 | } |
236 | } | 290 | } |
237 | 291 | ||
238 | /* | 292 | /* |
239 | * Called on each cpu to initialize the per_cpu UV data area. | 293 | * Called on each cpu to initialize the per_cpu UV data area. |
294 | * ZZZ hotplug not supported yet | ||
240 | */ | 295 | */ |
241 | void __cpuinit uv_cpu_init(void) | 296 | void __cpuinit uv_cpu_init(void) |
242 | { | 297 | { |
@@ -246,5 +301,5 @@ void __cpuinit uv_cpu_init(void) | |||
246 | uv_blade_info[uv_numa_blade_id()].nr_online_cpus++; | 301 | uv_blade_info[uv_numa_blade_id()].nr_online_cpus++; |
247 | 302 | ||
248 | if (get_uv_system_type() == UV_NON_UNIQUE_APIC) | 303 | if (get_uv_system_type() == UV_NON_UNIQUE_APIC) |
249 | set_x2apic_extra_bits(uv_hub_info->local_nasid); | 304 | set_x2apic_extra_bits(uv_hub_info->pnode); |
250 | } | 305 | } |