root/arch/x86/kernel/apic/probe_32.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. default_x86_32_early_logical_apicid
  2. setup_apic_flat_routing
  3. default_apic_id_registered
  4. default_init_apic_ldr
  5. default_phys_pkg_id
  6. probe_default
  7. parse_apic
  8. default_setup_apic_routing
  9. generic_apic_probe
  10. default_acpi_madt_oem_check

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Default generic APIC driver. This handles up to 8 CPUs.
   4  *
   5  * Copyright 2003 Andi Kleen, SuSE Labs.
   6  *
   7  * Generic x86 APIC driver probe layer.
   8  */
   9 #include <linux/export.h>
  10 #include <linux/errno.h>
  11 #include <linux/smp.h>
  12 
  13 #include <asm/apic.h>
  14 #include <asm/acpi.h>
  15 
  16 #include "local.h"
  17 
  18 static int default_x86_32_early_logical_apicid(int cpu)
  19 {
  20         return 1 << cpu;
  21 }
  22 
  23 static void setup_apic_flat_routing(void)
  24 {
  25 #ifdef CONFIG_X86_IO_APIC
  26         printk(KERN_INFO
  27                 "Enabling APIC mode:  Flat.  Using %d I/O APICs\n",
  28                 nr_ioapics);
  29 #endif
  30 }
  31 
  32 static int default_apic_id_registered(void)
  33 {
  34         return physid_isset(read_apic_id(), phys_cpu_present_map);
  35 }
  36 
  37 /*
  38  * Set up the logical destination ID.  Intel recommends to set DFR, LDR and
  39  * TPR before enabling an APIC.  See e.g. "AP-388 82489DX User's Manual"
  40  * (Intel document number 292116).
  41  */
  42 static void default_init_apic_ldr(void)
  43 {
  44         unsigned long val;
  45 
  46         apic_write(APIC_DFR, APIC_DFR_VALUE);
  47         val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
  48         val |= SET_APIC_LOGICAL_ID(1UL << smp_processor_id());
  49         apic_write(APIC_LDR, val);
  50 }
  51 
  52 static int default_phys_pkg_id(int cpuid_apic, int index_msb)
  53 {
  54         return cpuid_apic >> index_msb;
  55 }
  56 
  57 /* should be called last. */
  58 static int probe_default(void)
  59 {
  60         return 1;
  61 }
  62 
  63 static struct apic apic_default __ro_after_init = {
  64 
  65         .name                           = "default",
  66         .probe                          = probe_default,
  67         .acpi_madt_oem_check            = NULL,
  68         .apic_id_valid                  = default_apic_id_valid,
  69         .apic_id_registered             = default_apic_id_registered,
  70 
  71         .irq_delivery_mode              = dest_Fixed,
  72         /* logical delivery broadcast to all CPUs: */
  73         .irq_dest_mode                  = 1,
  74 
  75         .disable_esr                    = 0,
  76         .dest_logical                   = APIC_DEST_LOGICAL,
  77         .check_apicid_used              = default_check_apicid_used,
  78 
  79         .init_apic_ldr                  = default_init_apic_ldr,
  80 
  81         .ioapic_phys_id_map             = default_ioapic_phys_id_map,
  82         .setup_apic_routing             = setup_apic_flat_routing,
  83         .cpu_present_to_apicid          = default_cpu_present_to_apicid,
  84         .apicid_to_cpu_present          = physid_set_mask_of_physid,
  85         .check_phys_apicid_present      = default_check_phys_apicid_present,
  86         .phys_pkg_id                    = default_phys_pkg_id,
  87 
  88         .get_apic_id                    = default_get_apic_id,
  89         .set_apic_id                    = NULL,
  90 
  91         .calc_dest_apicid               = apic_flat_calc_apicid,
  92 
  93         .send_IPI                       = default_send_IPI_single,
  94         .send_IPI_mask                  = default_send_IPI_mask_logical,
  95         .send_IPI_mask_allbutself       = default_send_IPI_mask_allbutself_logical,
  96         .send_IPI_allbutself            = default_send_IPI_allbutself,
  97         .send_IPI_all                   = default_send_IPI_all,
  98         .send_IPI_self                  = default_send_IPI_self,
  99 
 100         .inquire_remote_apic            = default_inquire_remote_apic,
 101 
 102         .read                           = native_apic_mem_read,
 103         .write                          = native_apic_mem_write,
 104         .eoi_write                      = native_apic_mem_write,
 105         .icr_read                       = native_apic_icr_read,
 106         .icr_write                      = native_apic_icr_write,
 107         .wait_icr_idle                  = native_apic_wait_icr_idle,
 108         .safe_wait_icr_idle             = native_safe_apic_wait_icr_idle,
 109 
 110         .x86_32_early_logical_apicid    = default_x86_32_early_logical_apicid,
 111 };
 112 
 113 apic_driver(apic_default);
 114 
 115 struct apic *apic __ro_after_init = &apic_default;
 116 EXPORT_SYMBOL_GPL(apic);
 117 
 118 static int cmdline_apic __initdata;
 119 static int __init parse_apic(char *arg)
 120 {
 121         struct apic **drv;
 122 
 123         if (!arg)
 124                 return -EINVAL;
 125 
 126         for (drv = __apicdrivers; drv < __apicdrivers_end; drv++) {
 127                 if (!strcmp((*drv)->name, arg)) {
 128                         apic = *drv;
 129                         cmdline_apic = 1;
 130                         return 0;
 131                 }
 132         }
 133 
 134         /* Parsed again by __setup for debug/verbose */
 135         return 0;
 136 }
 137 early_param("apic", parse_apic);
 138 
 139 void __init default_setup_apic_routing(void)
 140 {
 141         int version = boot_cpu_apic_version;
 142 
 143         if (num_possible_cpus() > 8) {
 144                 switch (boot_cpu_data.x86_vendor) {
 145                 case X86_VENDOR_INTEL:
 146                         if (!APIC_XAPIC(version)) {
 147                                 def_to_bigsmp = 0;
 148                                 break;
 149                         }
 150                         /* P4 and above */
 151                         /* fall through */
 152                 case X86_VENDOR_HYGON:
 153                 case X86_VENDOR_AMD:
 154                         def_to_bigsmp = 1;
 155                 }
 156         }
 157 
 158 #ifdef CONFIG_X86_BIGSMP
 159         /*
 160          * This is used to switch to bigsmp mode when
 161          * - There is no apic= option specified by the user
 162          * - generic_apic_probe() has chosen apic_default as the sub_arch
 163          * - we find more than 8 CPUs in acpi LAPIC listing with xAPIC support
 164          */
 165 
 166         if (!cmdline_apic && apic == &apic_default)
 167                 generic_bigsmp_probe();
 168 #endif
 169 
 170         if (apic->setup_apic_routing)
 171                 apic->setup_apic_routing();
 172 
 173         if (x86_platform.apic_post_init)
 174                 x86_platform.apic_post_init();
 175 }
 176 
 177 void __init generic_apic_probe(void)
 178 {
 179         if (!cmdline_apic) {
 180                 struct apic **drv;
 181 
 182                 for (drv = __apicdrivers; drv < __apicdrivers_end; drv++) {
 183                         if ((*drv)->probe()) {
 184                                 apic = *drv;
 185                                 break;
 186                         }
 187                 }
 188                 /* Not visible without early console */
 189                 if (drv == __apicdrivers_end)
 190                         panic("Didn't find an APIC driver");
 191         }
 192         printk(KERN_INFO "Using APIC driver %s\n", apic->name);
 193 }
 194 
 195 /* This function can switch the APIC even after the initial ->probe() */
 196 int __init default_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
 197 {
 198         struct apic **drv;
 199 
 200         for (drv = __apicdrivers; drv < __apicdrivers_end; drv++) {
 201                 if (!(*drv)->acpi_madt_oem_check)
 202                         continue;
 203                 if (!(*drv)->acpi_madt_oem_check(oem_id, oem_table_id))
 204                         continue;
 205 
 206                 if (!cmdline_apic) {
 207                         apic = *drv;
 208                         printk(KERN_INFO "Switched to APIC driver `%s'.\n",
 209                                apic->name);
 210                 }
 211                 return 1;
 212         }
 213         return 0;
 214 }

/* [<][>][^][v][top][bottom][index][help] */