Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright 2004 James Cleverdon, IBM.
0004  *
0005  * Flat APIC subarch code.
0006  *
0007  * Hacked for x86-64 by James Cleverdon from i386 architecture code by
0008  * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
0009  * James Cleverdon.
0010  */
0011 #include <linux/cpumask.h>
0012 #include <linux/export.h>
0013 #include <linux/acpi.h>
0014 
0015 #include <asm/jailhouse_para.h>
0016 #include <asm/apic.h>
0017 
0018 #include "local.h"
0019 
0020 static struct apic apic_physflat;
0021 static struct apic apic_flat;
0022 
0023 struct apic *apic __ro_after_init = &apic_flat;
0024 EXPORT_SYMBOL_GPL(apic);
0025 
0026 static int flat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
0027 {
0028     return 1;
0029 }
0030 
0031 /*
0032  * Set up the logical destination ID.
0033  *
0034  * Intel recommends to set DFR, LDR and TPR before enabling
0035  * an APIC.  See e.g. "AP-388 82489DX User's Manual" (Intel
0036  * document number 292116).  So here it goes...
0037  */
0038 void flat_init_apic_ldr(void)
0039 {
0040     unsigned long val;
0041     unsigned long num, id;
0042 
0043     num = smp_processor_id();
0044     id = 1UL << num;
0045     apic_write(APIC_DFR, APIC_DFR_FLAT);
0046     val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
0047     val |= SET_APIC_LOGICAL_ID(id);
0048     apic_write(APIC_LDR, val);
0049 }
0050 
0051 static void _flat_send_IPI_mask(unsigned long mask, int vector)
0052 {
0053     unsigned long flags;
0054 
0055     local_irq_save(flags);
0056     __default_send_IPI_dest_field(mask, vector, APIC_DEST_LOGICAL);
0057     local_irq_restore(flags);
0058 }
0059 
0060 static void flat_send_IPI_mask(const struct cpumask *cpumask, int vector)
0061 {
0062     unsigned long mask = cpumask_bits(cpumask)[0];
0063 
0064     _flat_send_IPI_mask(mask, vector);
0065 }
0066 
0067 static void
0068 flat_send_IPI_mask_allbutself(const struct cpumask *cpumask, int vector)
0069 {
0070     unsigned long mask = cpumask_bits(cpumask)[0];
0071     int cpu = smp_processor_id();
0072 
0073     if (cpu < BITS_PER_LONG)
0074         __clear_bit(cpu, &mask);
0075 
0076     _flat_send_IPI_mask(mask, vector);
0077 }
0078 
0079 static unsigned int flat_get_apic_id(unsigned long x)
0080 {
0081     return (x >> 24) & 0xFF;
0082 }
0083 
0084 static u32 set_apic_id(unsigned int id)
0085 {
0086     return (id & 0xFF) << 24;
0087 }
0088 
0089 static unsigned int read_xapic_id(void)
0090 {
0091     return flat_get_apic_id(apic_read(APIC_ID));
0092 }
0093 
0094 static int flat_apic_id_registered(void)
0095 {
0096     return physid_isset(read_xapic_id(), phys_cpu_present_map);
0097 }
0098 
0099 static int flat_phys_pkg_id(int initial_apic_id, int index_msb)
0100 {
0101     return initial_apic_id >> index_msb;
0102 }
0103 
0104 static int flat_probe(void)
0105 {
0106     return 1;
0107 }
0108 
0109 static struct apic apic_flat __ro_after_init = {
0110     .name               = "flat",
0111     .probe              = flat_probe,
0112     .acpi_madt_oem_check        = flat_acpi_madt_oem_check,
0113     .apic_id_valid          = default_apic_id_valid,
0114     .apic_id_registered     = flat_apic_id_registered,
0115 
0116     .delivery_mode          = APIC_DELIVERY_MODE_FIXED,
0117     .dest_mode_logical      = true,
0118 
0119     .disable_esr            = 0,
0120 
0121     .check_apicid_used      = NULL,
0122     .init_apic_ldr          = flat_init_apic_ldr,
0123     .ioapic_phys_id_map     = NULL,
0124     .setup_apic_routing     = NULL,
0125     .cpu_present_to_apicid      = default_cpu_present_to_apicid,
0126     .apicid_to_cpu_present      = NULL,
0127     .check_phys_apicid_present  = default_check_phys_apicid_present,
0128     .phys_pkg_id            = flat_phys_pkg_id,
0129 
0130     .get_apic_id            = flat_get_apic_id,
0131     .set_apic_id            = set_apic_id,
0132 
0133     .calc_dest_apicid       = apic_flat_calc_apicid,
0134 
0135     .send_IPI           = default_send_IPI_single,
0136     .send_IPI_mask          = flat_send_IPI_mask,
0137     .send_IPI_mask_allbutself   = flat_send_IPI_mask_allbutself,
0138     .send_IPI_allbutself        = default_send_IPI_allbutself,
0139     .send_IPI_all           = default_send_IPI_all,
0140     .send_IPI_self          = default_send_IPI_self,
0141 
0142     .inquire_remote_apic        = default_inquire_remote_apic,
0143 
0144     .read               = native_apic_mem_read,
0145     .write              = native_apic_mem_write,
0146     .eoi_write          = native_apic_mem_write,
0147     .icr_read           = native_apic_icr_read,
0148     .icr_write          = native_apic_icr_write,
0149     .wait_icr_idle          = native_apic_wait_icr_idle,
0150     .safe_wait_icr_idle     = native_safe_apic_wait_icr_idle,
0151 };
0152 
0153 /*
0154  * Physflat mode is used when there are more than 8 CPUs on a system.
0155  * We cannot use logical delivery in this case because the mask
0156  * overflows, so use physical mode.
0157  */
0158 static int physflat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
0159 {
0160 #ifdef CONFIG_ACPI
0161     /*
0162      * Quirk: some x86_64 machines can only use physical APIC mode
0163      * regardless of how many processors are present (x86_64 ES7000
0164      * is an example).
0165      */
0166     if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
0167         (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL)) {
0168         printk(KERN_DEBUG "system APIC only can use physical flat");
0169         return 1;
0170     }
0171 
0172     if (!strncmp(oem_id, "IBM", 3) && !strncmp(oem_table_id, "EXA", 3)) {
0173         printk(KERN_DEBUG "IBM Summit detected, will use apic physical");
0174         return 1;
0175     }
0176 #endif
0177 
0178     return 0;
0179 }
0180 
0181 static void physflat_init_apic_ldr(void)
0182 {
0183     /*
0184      * LDR and DFR are not involved in physflat mode, rather:
0185      * "In physical destination mode, the destination processor is
0186      * specified by its local APIC ID [...]." (Intel SDM, 10.6.2.1)
0187      */
0188 }
0189 
0190 static int physflat_probe(void)
0191 {
0192     if (apic == &apic_physflat || num_possible_cpus() > 8 ||
0193         jailhouse_paravirt())
0194         return 1;
0195 
0196     return 0;
0197 }
0198 
0199 static struct apic apic_physflat __ro_after_init = {
0200 
0201     .name               = "physical flat",
0202     .probe              = physflat_probe,
0203     .acpi_madt_oem_check        = physflat_acpi_madt_oem_check,
0204     .apic_id_valid          = default_apic_id_valid,
0205     .apic_id_registered     = flat_apic_id_registered,
0206 
0207     .delivery_mode          = APIC_DELIVERY_MODE_FIXED,
0208     .dest_mode_logical      = false,
0209 
0210     .disable_esr            = 0,
0211 
0212     .check_apicid_used      = NULL,
0213     .init_apic_ldr          = physflat_init_apic_ldr,
0214     .ioapic_phys_id_map     = NULL,
0215     .setup_apic_routing     = NULL,
0216     .cpu_present_to_apicid      = default_cpu_present_to_apicid,
0217     .apicid_to_cpu_present      = NULL,
0218     .check_phys_apicid_present  = default_check_phys_apicid_present,
0219     .phys_pkg_id            = flat_phys_pkg_id,
0220 
0221     .get_apic_id            = flat_get_apic_id,
0222     .set_apic_id            = set_apic_id,
0223 
0224     .calc_dest_apicid       = apic_default_calc_apicid,
0225 
0226     .send_IPI           = default_send_IPI_single_phys,
0227     .send_IPI_mask          = default_send_IPI_mask_sequence_phys,
0228     .send_IPI_mask_allbutself   = default_send_IPI_mask_allbutself_phys,
0229     .send_IPI_allbutself        = default_send_IPI_allbutself,
0230     .send_IPI_all           = default_send_IPI_all,
0231     .send_IPI_self          = default_send_IPI_self,
0232 
0233     .inquire_remote_apic        = default_inquire_remote_apic,
0234 
0235     .read               = native_apic_mem_read,
0236     .write              = native_apic_mem_write,
0237     .eoi_write          = native_apic_mem_write,
0238     .icr_read           = native_apic_icr_read,
0239     .icr_write          = native_apic_icr_write,
0240     .wait_icr_idle          = native_apic_wait_icr_idle,
0241     .safe_wait_icr_idle     = native_safe_apic_wait_icr_idle,
0242 };
0243 
0244 /*
0245  * We need to check for physflat first, so this order is important.
0246  */
0247 apic_drivers(apic_physflat, apic_flat);