linux/arch/x86/kernel/apic/probe_32.c
<<
>>
Prefs
   1/*
   2 * Default generic APIC driver. This handles up to 8 CPUs.
   3 *
   4 * Copyright 2003 Andi Kleen, SuSE Labs.
   5 * Subject to the GNU Public License, v.2
   6 *
   7 * Generic x86 APIC driver probe layer.
   8 */
   9#include <linux/threads.h>
  10#include <linux/cpumask.h>
  11#include <linux/module.h>
  12#include <linux/string.h>
  13#include <linux/kernel.h>
  14#include <linux/ctype.h>
  15#include <linux/init.h>
  16#include <linux/errno.h>
  17#include <asm/fixmap.h>
  18#include <asm/mpspec.h>
  19#include <asm/apicdef.h>
  20#include <asm/apic.h>
  21#include <asm/setup.h>
  22
  23#include <linux/smp.h>
  24#include <asm/ipi.h>
  25
  26#include <linux/interrupt.h>
  27#include <asm/acpi.h>
  28#include <asm/e820.h>
  29
  30#ifdef CONFIG_HOTPLUG_CPU
  31#define DEFAULT_SEND_IPI        (1)
  32#else
  33#define DEFAULT_SEND_IPI        (0)
  34#endif
  35
  36int no_broadcast = DEFAULT_SEND_IPI;
  37
  38static __init int no_ipi_broadcast(char *str)
  39{
  40        get_option(&str, &no_broadcast);
  41        pr_info("Using %s mode\n",
  42                no_broadcast ? "No IPI Broadcast" : "IPI Broadcast");
  43        return 1;
  44}
  45__setup("no_ipi_broadcast=", no_ipi_broadcast);
  46
  47static int __init print_ipi_mode(void)
  48{
  49        pr_info("Using IPI %s mode\n",
  50                no_broadcast ? "No-Shortcut" : "Shortcut");
  51        return 0;
  52}
  53late_initcall(print_ipi_mode);
  54
  55static int default_x86_32_early_logical_apicid(int cpu)
  56{
  57        return 1 << cpu;
  58}
  59
  60static void setup_apic_flat_routing(void)
  61{
  62#ifdef CONFIG_X86_IO_APIC
  63        printk(KERN_INFO
  64                "Enabling APIC mode:  Flat.  Using %d I/O APICs\n",
  65                nr_ioapics);
  66#endif
  67}
  68
  69/* should be called last. */
  70static int probe_default(void)
  71{
  72        return 1;
  73}
  74
  75static struct apic apic_default = {
  76
  77        .name                           = "default",
  78        .probe                          = probe_default,
  79        .acpi_madt_oem_check            = NULL,
  80        .apic_id_valid                  = default_apic_id_valid,
  81        .apic_id_registered             = default_apic_id_registered,
  82
  83        .irq_delivery_mode              = dest_LowestPrio,
  84        /* logical delivery broadcast to all CPUs: */
  85        .irq_dest_mode                  = 1,
  86
  87        .target_cpus                    = default_target_cpus,
  88        .disable_esr                    = 0,
  89        .dest_logical                   = APIC_DEST_LOGICAL,
  90        .check_apicid_used              = default_check_apicid_used,
  91
  92        .vector_allocation_domain       = flat_vector_allocation_domain,
  93        .init_apic_ldr                  = default_init_apic_ldr,
  94
  95        .ioapic_phys_id_map             = default_ioapic_phys_id_map,
  96        .setup_apic_routing             = setup_apic_flat_routing,
  97        .cpu_present_to_apicid          = default_cpu_present_to_apicid,
  98        .apicid_to_cpu_present          = physid_set_mask_of_physid,
  99        .check_phys_apicid_present      = default_check_phys_apicid_present,
 100        .phys_pkg_id                    = default_phys_pkg_id,
 101
 102        .get_apic_id                    = default_get_apic_id,
 103        .set_apic_id                    = NULL,
 104        .apic_id_mask                   = 0x0F << 24,
 105
 106        .cpu_mask_to_apicid_and         = flat_cpu_mask_to_apicid_and,
 107
 108        .send_IPI                       = default_send_IPI_single,
 109        .send_IPI_mask                  = default_send_IPI_mask_logical,
 110        .send_IPI_mask_allbutself       = default_send_IPI_mask_allbutself_logical,
 111        .send_IPI_allbutself            = default_send_IPI_allbutself,
 112        .send_IPI_all                   = default_send_IPI_all,
 113        .send_IPI_self                  = default_send_IPI_self,
 114
 115        .inquire_remote_apic            = default_inquire_remote_apic,
 116
 117        .read                           = native_apic_mem_read,
 118        .write                          = native_apic_mem_write,
 119        .eoi_write                      = native_apic_mem_write,
 120        .icr_read                       = native_apic_icr_read,
 121        .icr_write                      = native_apic_icr_write,
 122        .wait_icr_idle                  = native_apic_wait_icr_idle,
 123        .safe_wait_icr_idle             = native_safe_apic_wait_icr_idle,
 124
 125        .x86_32_early_logical_apicid    = default_x86_32_early_logical_apicid,
 126};
 127
 128apic_driver(apic_default);
 129
 130struct apic *apic = &apic_default;
 131EXPORT_SYMBOL_GPL(apic);
 132
 133static int cmdline_apic __initdata;
 134static int __init parse_apic(char *arg)
 135{
 136        struct apic **drv;
 137
 138        if (!arg)
 139                return -EINVAL;
 140
 141        for (drv = __apicdrivers; drv < __apicdrivers_end; drv++) {
 142                if (!strcmp((*drv)->name, arg)) {
 143                        apic = *drv;
 144                        cmdline_apic = 1;
 145                        return 0;
 146                }
 147        }
 148
 149        /* Parsed again by __setup for debug/verbose */
 150        return 0;
 151}
 152early_param("apic", parse_apic);
 153
 154void __init default_setup_apic_routing(void)
 155{
 156        int version = apic_version[boot_cpu_physical_apicid];
 157
 158        if (num_possible_cpus() > 8) {
 159                switch (boot_cpu_data.x86_vendor) {
 160                case X86_VENDOR_INTEL:
 161                        if (!APIC_XAPIC(version)) {
 162                                def_to_bigsmp = 0;
 163                                break;
 164                        }
 165                        /* If P4 and above fall through */
 166                case X86_VENDOR_AMD:
 167                        def_to_bigsmp = 1;
 168                }
 169        }
 170
 171#ifdef CONFIG_X86_BIGSMP
 172        /*
 173         * This is used to switch to bigsmp mode when
 174         * - There is no apic= option specified by the user
 175         * - generic_apic_probe() has chosen apic_default as the sub_arch
 176         * - we find more than 8 CPUs in acpi LAPIC listing with xAPIC support
 177         */
 178
 179        if (!cmdline_apic && apic == &apic_default)
 180                generic_bigsmp_probe();
 181#endif
 182
 183        if (apic->setup_apic_routing)
 184                apic->setup_apic_routing();
 185
 186        if (x86_platform.apic_post_init)
 187                x86_platform.apic_post_init();
 188}
 189
 190void __init generic_apic_probe(void)
 191{
 192        if (!cmdline_apic) {
 193                struct apic **drv;
 194
 195                for (drv = __apicdrivers; drv < __apicdrivers_end; drv++) {
 196                        if ((*drv)->probe()) {
 197                                apic = *drv;
 198                                break;
 199                        }
 200                }
 201                /* Not visible without early console */
 202                if (drv == __apicdrivers_end)
 203                        panic("Didn't find an APIC driver");
 204        }
 205        printk(KERN_INFO "Using APIC driver %s\n", apic->name);
 206}
 207
 208/* This function can switch the APIC even after the initial ->probe() */
 209int __init default_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
 210{
 211        struct apic **drv;
 212
 213        for (drv = __apicdrivers; drv < __apicdrivers_end; drv++) {
 214                if (!(*drv)->acpi_madt_oem_check)
 215                        continue;
 216                if (!(*drv)->acpi_madt_oem_check(oem_id, oem_table_id))
 217                        continue;
 218
 219                if (!cmdline_apic) {
 220                        apic = *drv;
 221                        printk(KERN_INFO "Switched to APIC driver `%s'.\n",
 222                               apic->name);
 223                }
 224                return 1;
 225        }
 226        return 0;
 227}
 228