linux/arch/x86/kernel/apic/bigsmp_32.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * APIC driver for "bigsmp" xAPIC machines with more than 8 virtual CPUs.
   4 *
   5 * Drives the local APIC in "clustered mode".
   6 */
   7#include <linux/cpumask.h>
   8#include <linux/dmi.h>
   9#include <linux/smp.h>
  10
  11#include <asm/apic.h>
  12#include <asm/io_apic.h>
  13
  14#include "local.h"
  15
  16static unsigned bigsmp_get_apic_id(unsigned long x)
  17{
  18        return (x >> 24) & 0xFF;
  19}
  20
  21static int bigsmp_apic_id_registered(void)
  22{
  23        return 1;
  24}
  25
  26static bool bigsmp_check_apicid_used(physid_mask_t *map, int apicid)
  27{
  28        return false;
  29}
  30
  31static int bigsmp_early_logical_apicid(int cpu)
  32{
  33        /* on bigsmp, logical apicid is the same as physical */
  34        return early_per_cpu(x86_cpu_to_apicid, cpu);
  35}
  36
  37/*
  38 * bigsmp enables physical destination mode
  39 * and doesn't use LDR and DFR
  40 */
  41static void bigsmp_init_apic_ldr(void)
  42{
  43}
  44
  45static void bigsmp_setup_apic_routing(void)
  46{
  47        printk(KERN_INFO
  48                "Enabling APIC mode:  Physflat.  Using %d I/O APICs\n",
  49                nr_ioapics);
  50}
  51
  52static int bigsmp_cpu_present_to_apicid(int mps_cpu)
  53{
  54        if (mps_cpu < nr_cpu_ids)
  55                return (int) per_cpu(x86_bios_cpu_apicid, mps_cpu);
  56
  57        return BAD_APICID;
  58}
  59
  60static void bigsmp_ioapic_phys_id_map(physid_mask_t *phys_map, physid_mask_t *retmap)
  61{
  62        /* For clustered we don't have a good way to do this yet - hack */
  63        physids_promote(0xFFL, retmap);
  64}
  65
  66static int bigsmp_check_phys_apicid_present(int phys_apicid)
  67{
  68        return 1;
  69}
  70
  71static int bigsmp_phys_pkg_id(int cpuid_apic, int index_msb)
  72{
  73        return cpuid_apic >> index_msb;
  74}
  75
  76static void bigsmp_send_IPI_allbutself(int vector)
  77{
  78        default_send_IPI_mask_allbutself_phys(cpu_online_mask, vector);
  79}
  80
  81static void bigsmp_send_IPI_all(int vector)
  82{
  83        default_send_IPI_mask_sequence_phys(cpu_online_mask, vector);
  84}
  85
  86static int dmi_bigsmp; /* can be set by dmi scanners */
  87
  88static int hp_ht_bigsmp(const struct dmi_system_id *d)
  89{
  90        printk(KERN_NOTICE "%s detected: force use of apic=bigsmp\n", d->ident);
  91        dmi_bigsmp = 1;
  92
  93        return 0;
  94}
  95
  96
  97static const struct dmi_system_id bigsmp_dmi_table[] = {
  98        { hp_ht_bigsmp, "HP ProLiant DL760 G2",
  99                {       DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
 100                        DMI_MATCH(DMI_BIOS_VERSION, "P44-"),
 101                }
 102        },
 103
 104        { hp_ht_bigsmp, "HP ProLiant DL740",
 105                {       DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
 106                        DMI_MATCH(DMI_BIOS_VERSION, "P47-"),
 107                }
 108        },
 109        { } /* NULL entry stops DMI scanning */
 110};
 111
 112static int probe_bigsmp(void)
 113{
 114        if (def_to_bigsmp)
 115                dmi_bigsmp = 1;
 116        else
 117                dmi_check_system(bigsmp_dmi_table);
 118
 119        return dmi_bigsmp;
 120}
 121
 122static struct apic apic_bigsmp __ro_after_init = {
 123
 124        .name                           = "bigsmp",
 125        .probe                          = probe_bigsmp,
 126        .acpi_madt_oem_check            = NULL,
 127        .apic_id_valid                  = default_apic_id_valid,
 128        .apic_id_registered             = bigsmp_apic_id_registered,
 129
 130        .delivery_mode                  = APIC_DELIVERY_MODE_FIXED,
 131        .dest_mode_logical              = false,
 132
 133        .disable_esr                    = 1,
 134
 135        .check_apicid_used              = bigsmp_check_apicid_used,
 136        .init_apic_ldr                  = bigsmp_init_apic_ldr,
 137        .ioapic_phys_id_map             = bigsmp_ioapic_phys_id_map,
 138        .setup_apic_routing             = bigsmp_setup_apic_routing,
 139        .cpu_present_to_apicid          = bigsmp_cpu_present_to_apicid,
 140        .apicid_to_cpu_present          = physid_set_mask_of_physid,
 141        .check_phys_apicid_present      = bigsmp_check_phys_apicid_present,
 142        .phys_pkg_id                    = bigsmp_phys_pkg_id,
 143
 144        .get_apic_id                    = bigsmp_get_apic_id,
 145        .set_apic_id                    = NULL,
 146
 147        .calc_dest_apicid               = apic_default_calc_apicid,
 148
 149        .send_IPI                       = default_send_IPI_single_phys,
 150        .send_IPI_mask                  = default_send_IPI_mask_sequence_phys,
 151        .send_IPI_mask_allbutself       = NULL,
 152        .send_IPI_allbutself            = bigsmp_send_IPI_allbutself,
 153        .send_IPI_all                   = bigsmp_send_IPI_all,
 154        .send_IPI_self                  = default_send_IPI_self,
 155
 156        .inquire_remote_apic            = default_inquire_remote_apic,
 157
 158        .read                           = native_apic_mem_read,
 159        .write                          = native_apic_mem_write,
 160        .eoi_write                      = native_apic_mem_write,
 161        .icr_read                       = native_apic_icr_read,
 162        .icr_write                      = native_apic_icr_write,
 163        .wait_icr_idle                  = native_apic_wait_icr_idle,
 164        .safe_wait_icr_idle             = native_safe_apic_wait_icr_idle,
 165
 166        .x86_32_early_logical_apicid    = bigsmp_early_logical_apicid,
 167};
 168
 169void __init generic_bigsmp_probe(void)
 170{
 171        unsigned int cpu;
 172
 173        if (!probe_bigsmp())
 174                return;
 175
 176        apic = &apic_bigsmp;
 177
 178        for_each_possible_cpu(cpu) {
 179                if (early_per_cpu(x86_cpu_to_logical_apicid,
 180                                  cpu) == BAD_APICID)
 181                        continue;
 182                early_per_cpu(x86_cpu_to_logical_apicid, cpu) =
 183                        bigsmp_early_logical_apicid(cpu);
 184        }
 185
 186        pr_info("Overriding APIC driver with %s\n", apic_bigsmp.name);
 187}
 188
 189apic_driver(apic_bigsmp);
 190