Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/x86/kernel/apic/apic_numachip.c
26481 views
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
* Numascale NumaConnect-Specific APIC Code
7
*
8
* Copyright (C) 2011 Numascale AS. All rights reserved.
9
*
10
* Send feedback to <[email protected]>
11
*
12
*/
13
#include <linux/types.h>
14
#include <linux/init.h>
15
#include <linux/pgtable.h>
16
17
#include <asm/msr.h>
18
#include <asm/numachip/numachip.h>
19
#include <asm/numachip/numachip_csr.h>
20
21
22
#include "local.h"
23
24
u8 numachip_system __read_mostly;
25
static const struct apic apic_numachip1;
26
static const struct apic apic_numachip2;
27
static void (*numachip_apic_icr_write)(int apicid, unsigned int val) __read_mostly;
28
29
static u32 numachip1_get_apic_id(u32 x)
30
{
31
unsigned long value;
32
unsigned int id = (x >> 24) & 0xff;
33
34
if (static_cpu_has(X86_FEATURE_NODEID_MSR)) {
35
rdmsrq(MSR_FAM10H_NODE_ID, value);
36
id |= (value << 2) & 0xff00;
37
}
38
39
return id;
40
}
41
42
static u32 numachip2_get_apic_id(u32 x)
43
{
44
u64 mcfg;
45
46
rdmsrq(MSR_FAM10H_MMIO_CONF_BASE, mcfg);
47
return ((mcfg >> (28 - 8)) & 0xfff00) | (x >> 24);
48
}
49
50
static void numachip1_apic_icr_write(int apicid, unsigned int val)
51
{
52
write_lcsr(CSR_G3_EXT_IRQ_GEN, (apicid << 16) | val);
53
}
54
55
static void numachip2_apic_icr_write(int apicid, unsigned int val)
56
{
57
numachip2_write32_lcsr(NUMACHIP2_APIC_ICR, (apicid << 12) | val);
58
}
59
60
static int numachip_wakeup_secondary(u32 phys_apicid, unsigned long start_rip, unsigned int cpu)
61
{
62
numachip_apic_icr_write(phys_apicid, APIC_DM_INIT);
63
numachip_apic_icr_write(phys_apicid, APIC_DM_STARTUP |
64
(start_rip >> 12));
65
66
return 0;
67
}
68
69
static void numachip_send_IPI_one(int cpu, int vector)
70
{
71
int local_apicid, apicid = per_cpu(x86_cpu_to_apicid, cpu);
72
unsigned int dmode;
73
74
preempt_disable();
75
local_apicid = __this_cpu_read(x86_cpu_to_apicid);
76
77
/* Send via local APIC where non-local part matches */
78
if (!((apicid ^ local_apicid) >> NUMACHIP_LAPIC_BITS)) {
79
unsigned long flags;
80
81
local_irq_save(flags);
82
__default_send_IPI_dest_field(apicid, vector,
83
APIC_DEST_PHYSICAL);
84
local_irq_restore(flags);
85
preempt_enable();
86
return;
87
}
88
preempt_enable();
89
90
dmode = (vector == NMI_VECTOR) ? APIC_DM_NMI : APIC_DM_FIXED;
91
numachip_apic_icr_write(apicid, dmode | vector);
92
}
93
94
static void numachip_send_IPI_mask(const struct cpumask *mask, int vector)
95
{
96
unsigned int cpu;
97
98
for_each_cpu(cpu, mask)
99
numachip_send_IPI_one(cpu, vector);
100
}
101
102
static void numachip_send_IPI_mask_allbutself(const struct cpumask *mask,
103
int vector)
104
{
105
unsigned int this_cpu = smp_processor_id();
106
unsigned int cpu;
107
108
for_each_cpu(cpu, mask) {
109
if (cpu != this_cpu)
110
numachip_send_IPI_one(cpu, vector);
111
}
112
}
113
114
static void numachip_send_IPI_allbutself(int vector)
115
{
116
unsigned int this_cpu = smp_processor_id();
117
unsigned int cpu;
118
119
for_each_online_cpu(cpu) {
120
if (cpu != this_cpu)
121
numachip_send_IPI_one(cpu, vector);
122
}
123
}
124
125
static void numachip_send_IPI_all(int vector)
126
{
127
numachip_send_IPI_mask(cpu_online_mask, vector);
128
}
129
130
static void numachip_send_IPI_self(int vector)
131
{
132
apic_write(APIC_SELF_IPI, vector);
133
}
134
135
static int __init numachip1_probe(void)
136
{
137
return apic == &apic_numachip1;
138
}
139
140
static int __init numachip2_probe(void)
141
{
142
return apic == &apic_numachip2;
143
}
144
145
static void fixup_cpu_id(struct cpuinfo_x86 *c, int node)
146
{
147
u64 val;
148
u32 nodes = 1;
149
150
c->topo.llc_id = node;
151
152
/* Account for nodes per socket in multi-core-module processors */
153
if (boot_cpu_has(X86_FEATURE_NODEID_MSR)) {
154
rdmsrq(MSR_FAM10H_NODE_ID, val);
155
nodes = ((val >> 3) & 7) + 1;
156
}
157
158
c->topo.pkg_id = node / nodes;
159
}
160
161
static int __init numachip_system_init(void)
162
{
163
/* Map the LCSR area and set up the apic_icr_write function */
164
switch (numachip_system) {
165
case 1:
166
init_extra_mapping_uc(NUMACHIP_LCSR_BASE, NUMACHIP_LCSR_SIZE);
167
numachip_apic_icr_write = numachip1_apic_icr_write;
168
break;
169
case 2:
170
init_extra_mapping_uc(NUMACHIP2_LCSR_BASE, NUMACHIP2_LCSR_SIZE);
171
numachip_apic_icr_write = numachip2_apic_icr_write;
172
break;
173
default:
174
return 0;
175
}
176
177
x86_cpuinit.fixup_cpu_id = fixup_cpu_id;
178
x86_init.pci.arch_init = pci_numachip_init;
179
180
return 0;
181
}
182
early_initcall(numachip_system_init);
183
184
static int numachip1_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
185
{
186
if ((strncmp(oem_id, "NUMASC", 6) != 0) ||
187
(strncmp(oem_table_id, "NCONNECT", 8) != 0))
188
return 0;
189
190
numachip_system = 1;
191
192
return 1;
193
}
194
195
static int numachip2_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
196
{
197
if ((strncmp(oem_id, "NUMASC", 6) != 0) ||
198
(strncmp(oem_table_id, "NCONECT2", 8) != 0))
199
return 0;
200
201
numachip_system = 2;
202
203
return 1;
204
}
205
206
static const struct apic apic_numachip1 __refconst = {
207
.name = "NumaConnect system",
208
.probe = numachip1_probe,
209
.acpi_madt_oem_check = numachip1_acpi_madt_oem_check,
210
211
.dest_mode_logical = false,
212
213
.disable_esr = 0,
214
215
.cpu_present_to_apicid = default_cpu_present_to_apicid,
216
217
.max_apic_id = UINT_MAX,
218
.get_apic_id = numachip1_get_apic_id,
219
220
.calc_dest_apicid = apic_default_calc_apicid,
221
222
.send_IPI = numachip_send_IPI_one,
223
.send_IPI_mask = numachip_send_IPI_mask,
224
.send_IPI_mask_allbutself = numachip_send_IPI_mask_allbutself,
225
.send_IPI_allbutself = numachip_send_IPI_allbutself,
226
.send_IPI_all = numachip_send_IPI_all,
227
.send_IPI_self = numachip_send_IPI_self,
228
229
.wakeup_secondary_cpu = numachip_wakeup_secondary,
230
231
.read = native_apic_mem_read,
232
.write = native_apic_mem_write,
233
.eoi = native_apic_mem_eoi,
234
.icr_read = native_apic_icr_read,
235
.icr_write = native_apic_icr_write,
236
};
237
238
apic_driver(apic_numachip1);
239
240
static const struct apic apic_numachip2 __refconst = {
241
.name = "NumaConnect2 system",
242
.probe = numachip2_probe,
243
.acpi_madt_oem_check = numachip2_acpi_madt_oem_check,
244
245
.dest_mode_logical = false,
246
247
.disable_esr = 0,
248
249
.cpu_present_to_apicid = default_cpu_present_to_apicid,
250
251
.max_apic_id = UINT_MAX,
252
.get_apic_id = numachip2_get_apic_id,
253
254
.calc_dest_apicid = apic_default_calc_apicid,
255
256
.send_IPI = numachip_send_IPI_one,
257
.send_IPI_mask = numachip_send_IPI_mask,
258
.send_IPI_mask_allbutself = numachip_send_IPI_mask_allbutself,
259
.send_IPI_allbutself = numachip_send_IPI_allbutself,
260
.send_IPI_all = numachip_send_IPI_all,
261
.send_IPI_self = numachip_send_IPI_self,
262
263
.wakeup_secondary_cpu = numachip_wakeup_secondary,
264
265
.read = native_apic_mem_read,
266
.write = native_apic_mem_write,
267
.eoi = native_apic_mem_eoi,
268
.icr_read = native_apic_icr_read,
269
.icr_write = native_apic_icr_write,
270
};
271
272
apic_driver(apic_numachip2);
273
274