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