aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Travis <travis@sgi.com>2016-04-29 17:54:17 -0400
committerIngo Molnar <mingo@kernel.org>2016-05-04 02:48:49 -0400
commit405422d88c686e88b4241c0201fd96b61ab8bd77 (patch)
tree413a5da0ced27e3008c1a151fd05ea40f741a47a
parent906f3b20da8c6ec3eeef81753b4af9b6780e2edc (diff)
x86/platform/UV: Add UV4 addressing discovery function
UV4 requires early system wide addressing values. This involves the use of the CPUID instruction to obtain these values. The current function (detect_extended_topology()) in the kernel has been copied and streamlined, with the limitation that only CPU's used by UV architectures are supported. Tested-by: John Estabrook <estabrook@sgi.com> Tested-by: Gary Kroening <gfk@sgi.com> Tested-by: Nathan Zimmer <nzimmer@sgi.com> Signed-off-by: Mike Travis <travis@sgi.com> Reviewed-by: Dimitri Sivanich <sivanich@sgi.com> Cc: Andrew Banman <abanman@sgi.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Len Brown <len.brown@intel.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Russ Anderson <rja@sgi.com> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/20160429215405.155660884@asylum.americas.sgi.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/kernel/apic/x2apic_uv_x.c85
1 files changed, 72 insertions, 13 deletions
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
index afe1b039bd40..470f2dfe2709 100644
--- a/arch/x86/kernel/apic/x2apic_uv_x.c
+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -48,6 +48,16 @@ static u64 gru_start_paddr, gru_end_paddr;
48static u64 gru_dist_base, gru_first_node_paddr = -1LL, gru_last_node_paddr; 48static u64 gru_dist_base, gru_first_node_paddr = -1LL, gru_last_node_paddr;
49static u64 gru_dist_lmask, gru_dist_umask; 49static u64 gru_dist_lmask, gru_dist_umask;
50static union uvh_apicid uvh_apicid; 50static union uvh_apicid uvh_apicid;
51
52/* info derived from CPUID */
53static struct {
54 unsigned int apicid_shift;
55 unsigned int apicid_mask;
56 unsigned int socketid_shift; /* aka pnode_shift for UV1/2/3 */
57 unsigned int pnode_mask;
58 unsigned int gpa_shift;
59} uv_cpuid;
60
51int uv_min_hub_revision_id; 61int uv_min_hub_revision_id;
52EXPORT_SYMBOL_GPL(uv_min_hub_revision_id); 62EXPORT_SYMBOL_GPL(uv_min_hub_revision_id);
53unsigned int uv_apicid_hibits; 63unsigned int uv_apicid_hibits;
@@ -127,18 +137,65 @@ static int __init early_get_pnodeid(void)
127 } 137 }
128 138
129 uv_hub_info->hub_revision = uv_min_hub_revision_id; 139 uv_hub_info->hub_revision = uv_min_hub_revision_id;
130 pnode = (node_id.s.node_id >> 1) & ((1 << m_n_config.s.n_skt) - 1); 140 uv_cpuid.pnode_mask = (1 << m_n_config.s.n_skt) - 1;
141 pnode = (node_id.s.node_id >> 1) & uv_cpuid.pnode_mask;
142 uv_cpuid.gpa_shift = 46; /* default unless changed */
143
144 pr_info("UV: rev:%d part#:%x nodeid:%04x n_skt:%d pnmsk:%x pn:%x\n",
145 node_id.s.revision, node_id.s.part_number, node_id.s.node_id,
146 m_n_config.s.n_skt, uv_cpuid.pnode_mask, pnode);
131 return pnode; 147 return pnode;
132} 148}
133 149
134static void __init early_get_apic_pnode_shift(void) 150/* [copied from arch/x86/kernel/cpu/topology.c:detect_extended_topology()] */
151#define SMT_LEVEL 0 /* leaf 0xb SMT level */
152#define INVALID_TYPE 0 /* leaf 0xb sub-leaf types */
153#define SMT_TYPE 1
154#define CORE_TYPE 2
155#define LEAFB_SUBTYPE(ecx) (((ecx) >> 8) & 0xff)
156#define BITS_SHIFT_NEXT_LEVEL(eax) ((eax) & 0x1f)
157
158static void set_x2apic_bits(void)
159{
160 unsigned int eax, ebx, ecx, edx, sub_index;
161 unsigned int sid_shift;
162
163 cpuid(0, &eax, &ebx, &ecx, &edx);
164 if (eax < 0xb) {
165 pr_info("UV: CPU does not have CPUID.11\n");
166 return;
167 }
168 cpuid_count(0xb, SMT_LEVEL, &eax, &ebx, &ecx, &edx);
169 if (ebx == 0 || (LEAFB_SUBTYPE(ecx) != SMT_TYPE)) {
170 pr_info("UV: CPUID.11 not implemented\n");
171 return;
172 }
173 sid_shift = BITS_SHIFT_NEXT_LEVEL(eax);
174 sub_index = 1;
175 do {
176 cpuid_count(0xb, sub_index, &eax, &ebx, &ecx, &edx);
177 if (LEAFB_SUBTYPE(ecx) == CORE_TYPE) {
178 sid_shift = BITS_SHIFT_NEXT_LEVEL(eax);
179 break;
180 }
181 sub_index++;
182 } while (LEAFB_SUBTYPE(ecx) != INVALID_TYPE);
183 uv_cpuid.apicid_shift = 0;
184 uv_cpuid.apicid_mask = (~(-1 << sid_shift));
185 uv_cpuid.socketid_shift = sid_shift;
186}
187
188static void __init early_get_apic_socketid_shift(void)
135{ 189{
136 uvh_apicid.v = uv_early_read_mmr(UVH_APICID); 190 if (is_uv2_hub() || is_uv3_hub())
137 if (!uvh_apicid.v) 191 uvh_apicid.v = uv_early_read_mmr(UVH_APICID);
138 /* 192
139 * Old bios, use default value 193 set_x2apic_bits();
140 */ 194
141 uvh_apicid.s.pnode_shift = UV_APIC_PNODE_SHIFT; 195 pr_info("UV: apicid_shift:%d apicid_mask:0x%x\n",
196 uv_cpuid.apicid_shift, uv_cpuid.apicid_mask);
197 pr_info("UV: socketid_shift:%d pnode_mask:0x%x\n",
198 uv_cpuid.socketid_shift, uv_cpuid.pnode_mask);
142} 199}
143 200
144/* 201/*
@@ -186,7 +243,7 @@ static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
186 goto badbios; 243 goto badbios;
187 244
188 pnodeid = early_get_pnodeid(); 245 pnodeid = early_get_pnodeid();
189 early_get_apic_pnode_shift(); 246 early_get_apic_socketid_shift();
190 x86_platform.is_untracked_pat_range = uv_is_untracked_pat_range; 247 x86_platform.is_untracked_pat_range = uv_is_untracked_pat_range;
191 x86_platform.nmi_init = uv_nmi_init; 248 x86_platform.nmi_init = uv_nmi_init;
192 249
@@ -917,11 +974,13 @@ void __init uv_init_hub_info(struct uv_hub_info_s *hub_info)
917 hub_info->m_val = mn.m_val; 974 hub_info->m_val = mn.m_val;
918 hub_info->n_val = mn.n_val; 975 hub_info->n_val = mn.n_val;
919 hub_info->m_shift = mn.m_shift; 976 hub_info->m_shift = mn.m_shift;
920 hub_info->n_lshift = mn.n_lshift; 977 hub_info->n_lshift = mn.n_lshift ? mn.n_lshift : 0;
921 978
922 hub_info->hub_revision = uv_hub_info->hub_revision; 979 hub_info->hub_revision = uv_hub_info->hub_revision;
923 hub_info->pnode_mask = (1 << mn.n_val) - 1; 980 hub_info->pnode_mask = uv_cpuid.pnode_mask;
924 hub_info->gpa_mask = (1UL << (mn.m_val + mn.n_val)) - 1; 981 hub_info->gpa_mask = mn.m_val ?
982 (1UL << (mn.m_val + mn.n_val)) - 1 :
983 (1UL << uv_cpuid.gpa_shift) - 1;
925 984
926 node_id.v = uv_read_local_mmr(UVH_NODE_ID); 985 node_id.v = uv_read_local_mmr(UVH_NODE_ID);
927 hub_info->gnode_extra = 986 hub_info->gnode_extra =
@@ -937,7 +996,7 @@ void __init uv_init_hub_info(struct uv_hub_info_s *hub_info)
937 get_lowmem_redirect( 996 get_lowmem_redirect(
938 &hub_info->lowmem_remap_base, &hub_info->lowmem_remap_top); 997 &hub_info->lowmem_remap_base, &hub_info->lowmem_remap_top);
939 998
940 hub_info->apic_pnode_shift = uvh_apicid.s.pnode_shift; 999 hub_info->apic_pnode_shift = uv_cpuid.socketid_shift;
941 1000
942 /* show system specific info */ 1001 /* show system specific info */
943 pr_info("UV: N:%d M:%d m_shift:%d n_lshift:%d\n", 1002 pr_info("UV: N:%d M:%d m_shift:%d n_lshift:%d\n",