xref: /openbmc/linux/arch/x86/kernel/apic/apic_flat_64.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
17e300dabSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2f62bae50SIngo Molnar /*
3f62bae50SIngo Molnar  * Copyright 2004 James Cleverdon, IBM.
4f62bae50SIngo Molnar  *
5f62bae50SIngo Molnar  * Flat APIC subarch code.
6f62bae50SIngo Molnar  *
7f62bae50SIngo Molnar  * Hacked for x86-64 by James Cleverdon from i386 architecture code by
8f62bae50SIngo Molnar  * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
9f62bae50SIngo Molnar  * James Cleverdon.
10f62bae50SIngo Molnar  */
11f62bae50SIngo Molnar #include <linux/cpumask.h>
12186f4360SPaul Gortmaker #include <linux/export.h>
13521b82feSThomas Gleixner #include <linux/acpi.h>
14f62bae50SIngo Molnar 
15ad3bc25aSBorislav Petkov #include <asm/jailhouse_para.h>
16521b82feSThomas Gleixner #include <asm/apic.h>
178b542da3SThomas Gleixner 
18c94f0718SThomas Gleixner #include "local.h"
19f62bae50SIngo Molnar 
201a8880a1SSuresh Siddha static struct apic apic_physflat;
211a8880a1SSuresh Siddha static struct apic apic_flat;
221a8880a1SSuresh Siddha 
23404f6aacSKees Cook struct apic *apic __ro_after_init = &apic_flat;
241a8880a1SSuresh Siddha EXPORT_SYMBOL_GPL(apic);
251a8880a1SSuresh Siddha 
flat_acpi_madt_oem_check(char * oem_id,char * oem_table_id)26f62bae50SIngo Molnar static int flat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
27f62bae50SIngo Molnar {
28f62bae50SIngo Molnar 	return 1;
29f62bae50SIngo Molnar }
30f62bae50SIngo Molnar 
_flat_send_IPI_mask(unsigned long mask,int vector)31fe2f9546SDenys Vlasenko static void _flat_send_IPI_mask(unsigned long mask, int vector)
32f62bae50SIngo Molnar {
33f62bae50SIngo Molnar 	unsigned long flags;
34f62bae50SIngo Molnar 
35f62bae50SIngo Molnar 	local_irq_save(flags);
3622e0db42SThomas Gleixner 	__default_send_IPI_dest_field(mask, vector, APIC_DEST_LOGICAL);
37f62bae50SIngo Molnar 	local_irq_restore(flags);
38f62bae50SIngo Molnar }
39f62bae50SIngo Molnar 
flat_send_IPI_mask(const struct cpumask * cpumask,int vector)40f62bae50SIngo Molnar static void flat_send_IPI_mask(const struct cpumask *cpumask, int vector)
41f62bae50SIngo Molnar {
42f62bae50SIngo Molnar 	unsigned long mask = cpumask_bits(cpumask)[0];
43f62bae50SIngo Molnar 
44f62bae50SIngo Molnar 	_flat_send_IPI_mask(mask, vector);
45f62bae50SIngo Molnar }
46f62bae50SIngo Molnar 
47f62bae50SIngo Molnar static void
flat_send_IPI_mask_allbutself(const struct cpumask * cpumask,int vector)48f62bae50SIngo Molnar flat_send_IPI_mask_allbutself(const struct cpumask *cpumask, int vector)
49f62bae50SIngo Molnar {
50f62bae50SIngo Molnar 	unsigned long mask = cpumask_bits(cpumask)[0];
51f62bae50SIngo Molnar 	int cpu = smp_processor_id();
52f62bae50SIngo Molnar 
53f62bae50SIngo Molnar 	if (cpu < BITS_PER_LONG)
54dde3626fSNadav Amit 		__clear_bit(cpu, &mask);
55f62bae50SIngo Molnar 
56f62bae50SIngo Molnar 	_flat_send_IPI_mask(mask, vector);
57f62bae50SIngo Molnar }
58f62bae50SIngo Molnar 
flat_get_apic_id(unsigned long x)59f62bae50SIngo Molnar static unsigned int flat_get_apic_id(unsigned long x)
60f62bae50SIngo Molnar {
61f148b41eSMasahiro Yamada 	return (x >> 24) & 0xFF;
62f62bae50SIngo Molnar }
63f62bae50SIngo Molnar 
set_apic_id(unsigned int id)64727657e6SThomas Gleixner static u32 set_apic_id(unsigned int id)
65f62bae50SIngo Molnar {
66f148b41eSMasahiro Yamada 	return (id & 0xFF) << 24;
67f62bae50SIngo Molnar }
68f62bae50SIngo Molnar 
flat_phys_pkg_id(int initial_apic_id,int index_msb)69f62bae50SIngo Molnar static int flat_phys_pkg_id(int initial_apic_id, int index_msb)
70f62bae50SIngo Molnar {
712759c328SYinghai Lu 	return initial_apic_id >> index_msb;
72f62bae50SIngo Molnar }
73f62bae50SIngo Molnar 
flat_probe(void)74e8524b2fSYinghai Lu static int flat_probe(void)
75e8524b2fSYinghai Lu {
76e8524b2fSYinghai Lu 	return 1;
77e8524b2fSYinghai Lu }
78e8524b2fSYinghai Lu 
79404f6aacSKees Cook static struct apic apic_flat __ro_after_init = {
80f62bae50SIngo Molnar 	.name				= "flat",
81e8524b2fSYinghai Lu 	.probe				= flat_probe,
82f62bae50SIngo Molnar 	.acpi_madt_oem_check		= flat_acpi_madt_oem_check,
835a3a46bdSThomas Gleixner 	.apic_id_registered		= default_apic_id_registered,
84f62bae50SIngo Molnar 
8572161299SThomas Gleixner 	.delivery_mode			= APIC_DELIVERY_MODE_FIXED,
868c44963bSThomas Gleixner 	.dest_mode_logical		= true,
87f62bae50SIngo Molnar 
88f62bae50SIngo Molnar 	.disable_esr			= 0,
89e57d04e5SThomas Gleixner 
902f6df03fSThomas Gleixner 	.init_apic_ldr			= default_init_apic_ldr,
91f62bae50SIngo Molnar 	.cpu_present_to_apicid		= default_cpu_present_to_apicid,
92f62bae50SIngo Molnar 	.phys_pkg_id			= flat_phys_pkg_id,
93f62bae50SIngo Molnar 
94d92e5e7cSThomas Gleixner 	.max_apic_id			= 0xFE,
95f62bae50SIngo Molnar 	.get_apic_id			= flat_get_apic_id,
96f62bae50SIngo Molnar 	.set_apic_id			= set_apic_id,
97f62bae50SIngo Molnar 
989f9e3bb1SThomas Gleixner 	.calc_dest_apicid		= apic_flat_calc_apicid,
99f62bae50SIngo Molnar 
1006153058aSThomas Gleixner 	.send_IPI			= default_send_IPI_single,
101f62bae50SIngo Molnar 	.send_IPI_mask			= flat_send_IPI_mask,
102f62bae50SIngo Molnar 	.send_IPI_mask_allbutself	= flat_send_IPI_mask_allbutself,
1032510d09eSThomas Gleixner 	.send_IPI_allbutself		= default_send_IPI_allbutself,
1042510d09eSThomas Gleixner 	.send_IPI_all			= default_send_IPI_all,
1052510d09eSThomas Gleixner 	.send_IPI_self			= default_send_IPI_self,
106f62bae50SIngo Molnar 
107f62bae50SIngo Molnar 	.read				= native_apic_mem_read,
108f62bae50SIngo Molnar 	.write				= native_apic_mem_write,
109185c8f33SThomas Gleixner 	.eoi				= native_apic_mem_eoi,
110f62bae50SIngo Molnar 	.icr_read			= native_apic_icr_read,
111f62bae50SIngo Molnar 	.icr_write			= native_apic_icr_write,
112cfebd007SThomas Gleixner 	.wait_icr_idle			= apic_mem_wait_icr_idle,
113e7b6a023SThomas Gleixner 	.safe_wait_icr_idle		= apic_mem_wait_icr_idle_timeout,
114f62bae50SIngo Molnar };
115f62bae50SIngo Molnar 
116f62bae50SIngo Molnar /*
117e34b7005SJasper Spaans  * Physflat mode is used when there are more than 8 CPUs on a system.
118f62bae50SIngo Molnar  * We cannot use logical delivery in this case because the mask
119f62bae50SIngo Molnar  * overflows, so use physical mode.
120f62bae50SIngo Molnar  */
physflat_acpi_madt_oem_check(char * oem_id,char * oem_table_id)121f62bae50SIngo Molnar static int physflat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
122f62bae50SIngo Molnar {
123f62bae50SIngo Molnar #ifdef CONFIG_ACPI
124f62bae50SIngo Molnar 	/*
125f62bae50SIngo Molnar 	 * Quirk: some x86_64 machines can only use physical APIC mode
126f62bae50SIngo Molnar 	 * regardless of how many processors are present (x86_64 ES7000
127f62bae50SIngo Molnar 	 * is an example).
128f62bae50SIngo Molnar 	 */
12961fe91e1SYinghai Lu 	if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
130f62bae50SIngo Molnar 		(acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL)) {
131f62bae50SIngo Molnar 		printk(KERN_DEBUG "system APIC only can use physical flat");
132f62bae50SIngo Molnar 		return 1;
133f62bae50SIngo Molnar 	}
134dfea91d5SSuresh Siddha 
135dfea91d5SSuresh Siddha 	if (!strncmp(oem_id, "IBM", 3) && !strncmp(oem_table_id, "EXA", 3)) {
136dfea91d5SSuresh Siddha 		printk(KERN_DEBUG "IBM Summit detected, will use apic physical");
137dfea91d5SSuresh Siddha 		return 1;
138dfea91d5SSuresh Siddha 	}
139f62bae50SIngo Molnar #endif
140f62bae50SIngo Molnar 
141f62bae50SIngo Molnar 	return 0;
142f62bae50SIngo Molnar }
143f62bae50SIngo Molnar 
physflat_probe(void)1449ebd680bSSuresh Siddha static int physflat_probe(void)
1459ebd680bSSuresh Siddha {
146*3af1e415SThomas Gleixner 	return apic == &apic_physflat || num_possible_cpus() > 8 || jailhouse_paravirt();
1479ebd680bSSuresh Siddha }
1489ebd680bSSuresh Siddha 
149404f6aacSKees Cook static struct apic apic_physflat __ro_after_init = {
150f62bae50SIngo Molnar 
151f62bae50SIngo Molnar 	.name				= "physical flat",
1529ebd680bSSuresh Siddha 	.probe				= physflat_probe,
153f62bae50SIngo Molnar 	.acpi_madt_oem_check		= physflat_acpi_madt_oem_check,
1545a3a46bdSThomas Gleixner 	.apic_id_registered		= default_apic_id_registered,
155f62bae50SIngo Molnar 
15672161299SThomas Gleixner 	.delivery_mode			= APIC_DELIVERY_MODE_FIXED,
1578c44963bSThomas Gleixner 	.dest_mode_logical		= false,
158f62bae50SIngo Molnar 
159f62bae50SIngo Molnar 	.disable_esr			= 0,
160e57d04e5SThomas Gleixner 
161f62bae50SIngo Molnar 	.check_apicid_used		= NULL,
162f62bae50SIngo Molnar 	.ioapic_phys_id_map		= NULL,
163f62bae50SIngo Molnar 	.cpu_present_to_apicid		= default_cpu_present_to_apicid,
164f62bae50SIngo Molnar 	.phys_pkg_id			= flat_phys_pkg_id,
165f62bae50SIngo Molnar 
166d92e5e7cSThomas Gleixner 	.max_apic_id			= 0xFE,
167f62bae50SIngo Molnar 	.get_apic_id			= flat_get_apic_id,
168f62bae50SIngo Molnar 	.set_apic_id			= set_apic_id,
169f62bae50SIngo Molnar 
1709f9e3bb1SThomas Gleixner 	.calc_dest_apicid		= apic_default_calc_apicid,
171f62bae50SIngo Molnar 
17268cd88ffSThomas Gleixner 	.send_IPI			= default_send_IPI_single_phys,
173449112f4SThomas Gleixner 	.send_IPI_mask			= default_send_IPI_mask_sequence_phys,
174449112f4SThomas Gleixner 	.send_IPI_mask_allbutself	= default_send_IPI_mask_allbutself_phys,
1752510d09eSThomas Gleixner 	.send_IPI_allbutself		= default_send_IPI_allbutself,
1762510d09eSThomas Gleixner 	.send_IPI_all			= default_send_IPI_all,
1772510d09eSThomas Gleixner 	.send_IPI_self			= default_send_IPI_self,
178f62bae50SIngo Molnar 
179f62bae50SIngo Molnar 	.read				= native_apic_mem_read,
180f62bae50SIngo Molnar 	.write				= native_apic_mem_write,
181185c8f33SThomas Gleixner 	.eoi				= native_apic_mem_eoi,
182f62bae50SIngo Molnar 	.icr_read			= native_apic_icr_read,
183f62bae50SIngo Molnar 	.icr_write			= native_apic_icr_write,
184cfebd007SThomas Gleixner 	.wait_icr_idle			= apic_mem_wait_icr_idle,
185e7b6a023SThomas Gleixner 	.safe_wait_icr_idle		= apic_mem_wait_icr_idle_timeout,
186f62bae50SIngo Molnar };
187107e0e0cSSuresh Siddha 
188107e0e0cSSuresh Siddha /*
189107e0e0cSSuresh Siddha  * We need to check for physflat first, so this order is important.
190107e0e0cSSuresh Siddha  */
191107e0e0cSSuresh Siddha apic_drivers(apic_physflat, apic_flat);
192