File Index
Files and directories
Sign in
FILE

apic_numachip.c

File preview with syntax highlighting.

linux-6.19.14/arch/x86/kernel/apic/apic_numachip.c C
  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 <support@numascale.com>
 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
 24u8 numachip_system __read_mostly;
 25static const struct apic apic_numachip1;
 26static const struct apic apic_numachip2;
 27static void (*numachip_apic_icr_write)(int apicid, unsigned int val) __read_mostly;
 28
 29static 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
 42static 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
 50static void numachip1_apic_icr_write(int apicid, unsigned int val)
 51{
 52	write_lcsr(CSR_G3_EXT_IRQ_GEN, (apicid << 16) | val);
 53}
 54
 55static void numachip2_apic_icr_write(int apicid, unsigned int val)
 56{
 57	numachip2_write32_lcsr(NUMACHIP2_APIC_ICR, (apicid << 12) | val);
 58}
 59
 60static 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
 69static 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
 94static 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
102static 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
114static 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
125static void numachip_send_IPI_all(int vector)
126{
127	numachip_send_IPI_mask(cpu_online_mask, vector);
128}
129
130static void numachip_send_IPI_self(int vector)
131{
132	apic_write(APIC_SELF_IPI, vector);
133}
134
135static int __init numachip1_probe(void)
136{
137	return apic == &apic_numachip1;
138}
139
140static int __init numachip2_probe(void)
141{
142	return apic == &apic_numachip2;
143}
144
145static 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
161static 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}
182early_initcall(numachip_system_init);
183
184static 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
195static 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
206static 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
238apic_driver(apic_numachip1);
239
240static 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
272apic_driver(apic_numachip2);
~/ Read-only file preview.