linux/arch/x86/kernel/apic/apic_numachip.c
<<
>>
Prefs
   1/*
   2 * This file is subject to the terms and conditions of the GNU General Public
   3 * License.  See the file "COPYING" in the main directory of this archive
   4 * for more details.
   5 *
   6 * Numascale NumaConnect-Specific APIC Code
   7 *
   8 * Copyright (C) 2011 Numascale AS. All rights reserved.
   9 *
  10 * Send feedback to <support@numascale.com>
  11 *
  12 */
  13
  14#include <linux/init.h>
  15
  16#include <asm/numachip/numachip.h>
  17#include <asm/numachip/numachip_csr.h>
  18#include <asm/ipi.h>
  19#include <asm/apic_flat_64.h>
  20#include <asm/pgtable.h>
  21#include <asm/pci_x86.h>
  22
  23u8 numachip_system __read_mostly;
  24static const struct apic apic_numachip1;
  25static const struct apic apic_numachip2;
  26static void (*numachip_apic_icr_write)(int apicid, unsigned int val) __read_mostly;
  27
  28static unsigned int numachip1_get_apic_id(unsigned long x)
  29{
  30        unsigned long value;
  31        unsigned int id = (x >> 24) & 0xff;
  32
  33        if (static_cpu_has(X86_FEATURE_NODEID_MSR)) {
  34                rdmsrl(MSR_FAM10H_NODE_ID, value);
  35                id |= (value << 2) & 0xff00;
  36        }
  37
  38        return id;
  39}
  40
  41static unsigned long numachip1_set_apic_id(unsigned int id)
  42{
  43        return (id & 0xff) << 24;
  44}
  45
  46static unsigned int numachip2_get_apic_id(unsigned long x)
  47{
  48        u64 mcfg;
  49
  50        rdmsrl(MSR_FAM10H_MMIO_CONF_BASE, mcfg);
  51        return ((mcfg >> (28 - 8)) & 0xfff00) | (x >> 24);
  52}
  53
  54static unsigned long numachip2_set_apic_id(unsigned int id)
  55{
  56        return id << 24;
  57}
  58
  59static int numachip_apic_id_valid(int apicid)
  60{
  61        /* Trust what bootloader passes in MADT */
  62        return 1;
  63}
  64
  65static int numachip_apic_id_registered(void)
  66{
  67        return 1;
  68}
  69
  70static int numachip_phys_pkg_id(int initial_apic_id, int index_msb)
  71{
  72        return initial_apic_id >> index_msb;
  73}
  74
  75static void numachip1_apic_icr_write(int apicid, unsigned int val)
  76{
  77        write_lcsr(CSR_G3_EXT_IRQ_GEN, (apicid << 16) | val);
  78}
  79
  80static void numachip2_apic_icr_write(int apicid, unsigned int val)
  81{
  82        numachip2_write32_lcsr(NUMACHIP2_APIC_ICR, (apicid << 12) | val);
  83}
  84
  85static int numachip_wakeup_secondary(int phys_apicid, unsigned long start_rip)
  86{
  87        numachip_apic_icr_write(phys_apicid, APIC_DM_INIT);
  88        numachip_apic_icr_write(phys_apicid, APIC_DM_STARTUP |
  89                (start_rip >> 12));
  90
  91        return 0;
  92}
  93
  94static void numachip_send_IPI_one(int cpu, int vector)
  95{
  96        int local_apicid, apicid = per_cpu(x86_cpu_to_apicid, cpu);
  97        unsigned int dmode;
  98
  99        preempt_disable();
 100        local_apicid = __this_cpu_read(x86_cpu_to_apicid);
 101
 102        /* Send via local APIC where non-local part matches */
 103        if (!((apicid ^ local_apicid) >> NUMACHIP_LAPIC_BITS)) {
 104                unsigned long flags;
 105
 106                local_irq_save(flags);
 107                __default_send_IPI_dest_field(apicid, vector,
 108                        APIC_DEST_PHYSICAL);
 109                local_irq_restore(flags);
 110                preempt_enable();
 111                return;
 112        }
 113        preempt_enable();
 114
 115        dmode = (vector == NMI_VECTOR) ? APIC_DM_NMI : APIC_DM_FIXED;
 116        numachip_apic_icr_write(apicid, dmode | vector);
 117}
 118
 119static void numachip_send_IPI_mask(const struct cpumask *mask, int vector)
 120{
 121        unsigned int cpu;
 122
 123        for_each_cpu(cpu, mask)
 124                numachip_send_IPI_one(cpu, vector);
 125}
 126
 127static void numachip_send_IPI_mask_allbutself(const struct cpumask *mask,
 128                                                int vector)
 129{
 130        unsigned int this_cpu = smp_processor_id();
 131        unsigned int cpu;
 132
 133        for_each_cpu(cpu, mask) {
 134                if (cpu != this_cpu)
 135                        numachip_send_IPI_one(cpu, vector);
 136        }
 137}
 138
 139static void numachip_send_IPI_allbutself(int vector)
 140{
 141        unsigned int this_cpu = smp_processor_id();
 142        unsigned int cpu;
 143
 144        for_each_online_cpu(cpu) {
 145                if (cpu != this_cpu)
 146                        numachip_send_IPI_one(cpu, vector);
 147        }
 148}
 149
 150static void numachip_send_IPI_all(int vector)
 151{
 152        numachip_send_IPI_mask(cpu_online_mask, vector);
 153}
 154
 155static void numachip_send_IPI_self(int vector)
 156{
 157        apic_write(APIC_SELF_IPI, vector);
 158}
 159
 160static int __init numachip1_probe(void)
 161{
 162        return apic == &apic_numachip1;
 163}
 164
 165static int __init numachip2_probe(void)
 166{
 167        return apic == &apic_numachip2;
 168}
 169
 170static void fixup_cpu_id(struct cpuinfo_x86 *c, int node)
 171{
 172        u64 val;
 173        u32 nodes = 1;
 174
 175        this_cpu_write(cpu_llc_id, node);
 176
 177        /* Account for nodes per socket in multi-core-module processors */
 178        if (static_cpu_has(X86_FEATURE_NODEID_MSR)) {
 179                rdmsrl(MSR_FAM10H_NODE_ID, val);
 180                nodes = ((val >> 3) & 7) + 1;
 181        }
 182
 183        c->phys_proc_id = node / nodes;
 184}
 185
 186static int __init numachip_system_init(void)
 187{
 188        /* Map the LCSR area and set up the apic_icr_write function */
 189        switch (numachip_system) {
 190        case 1:
 191                init_extra_mapping_uc(NUMACHIP_LCSR_BASE, NUMACHIP_LCSR_SIZE);
 192                numachip_apic_icr_write = numachip1_apic_icr_write;
 193                break;
 194        case 2:
 195                init_extra_mapping_uc(NUMACHIP2_LCSR_BASE, NUMACHIP2_LCSR_SIZE);
 196                numachip_apic_icr_write = numachip2_apic_icr_write;
 197                break;
 198        default:
 199                return 0;
 200        }
 201
 202        x86_cpuinit.fixup_cpu_id = fixup_cpu_id;
 203        x86_init.pci.arch_init = pci_numachip_init;
 204
 205        return 0;
 206}
 207early_initcall(numachip_system_init);
 208
 209static int numachip1_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
 210{
 211        if ((strncmp(oem_id, "NUMASC", 6) != 0) ||
 212            (strncmp(oem_table_id, "NCONNECT", 8) != 0))
 213                return 0;
 214
 215        numachip_system = 1;
 216
 217        return 1;
 218}
 219
 220static int numachip2_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
 221{
 222        if ((strncmp(oem_id, "NUMASC", 6) != 0) ||
 223            (strncmp(oem_table_id, "NCONECT2", 8) != 0))
 224                return 0;
 225
 226        numachip_system = 2;
 227
 228        return 1;
 229}
 230
 231/* APIC IPIs are queued */
 232static void numachip_apic_wait_icr_idle(void)
 233{
 234}
 235
 236/* APIC NMI IPIs are queued */
 237static u32 numachip_safe_apic_wait_icr_idle(void)
 238{
 239        return 0;
 240}
 241
 242static const struct apic apic_numachip1 __refconst = {
 243        .name                           = "NumaConnect system",
 244        .probe                          = numachip1_probe,
 245        .acpi_madt_oem_check            = numachip1_acpi_madt_oem_check,
 246        .apic_id_valid                  = numachip_apic_id_valid,
 247        .apic_id_registered             = numachip_apic_id_registered,
 248
 249        .irq_delivery_mode              = dest_Fixed,
 250        .irq_dest_mode                  = 0, /* physical */
 251
 252        .target_cpus                    = online_target_cpus,
 253        .disable_esr                    = 0,
 254        .dest_logical                   = 0,
 255        .check_apicid_used              = NULL,
 256
 257        .vector_allocation_domain       = default_vector_allocation_domain,
 258        .init_apic_ldr                  = flat_init_apic_ldr,
 259
 260        .ioapic_phys_id_map             = NULL,
 261        .setup_apic_routing             = NULL,
 262        .cpu_present_to_apicid          = default_cpu_present_to_apicid,
 263        .apicid_to_cpu_present          = NULL,
 264        .check_phys_apicid_present      = default_check_phys_apicid_present,
 265        .phys_pkg_id                    = numachip_phys_pkg_id,
 266
 267        .get_apic_id                    = numachip1_get_apic_id,
 268        .set_apic_id                    = numachip1_set_apic_id,
 269
 270        .cpu_mask_to_apicid_and         = default_cpu_mask_to_apicid_and,
 271
 272        .send_IPI                       = numachip_send_IPI_one,
 273        .send_IPI_mask                  = numachip_send_IPI_mask,
 274        .send_IPI_mask_allbutself       = numachip_send_IPI_mask_allbutself,
 275        .send_IPI_allbutself            = numachip_send_IPI_allbutself,
 276        .send_IPI_all                   = numachip_send_IPI_all,
 277        .send_IPI_self                  = numachip_send_IPI_self,
 278
 279        .wakeup_secondary_cpu           = numachip_wakeup_secondary,
 280        .inquire_remote_apic            = NULL, /* REMRD not supported */
 281
 282        .read                           = native_apic_mem_read,
 283        .write                          = native_apic_mem_write,
 284        .eoi_write                      = native_apic_mem_write,
 285        .icr_read                       = native_apic_icr_read,
 286        .icr_write                      = native_apic_icr_write,
 287        .wait_icr_idle                  = numachip_apic_wait_icr_idle,
 288        .safe_wait_icr_idle             = numachip_safe_apic_wait_icr_idle,
 289};
 290
 291apic_driver(apic_numachip1);
 292
 293static const struct apic apic_numachip2 __refconst = {
 294        .name                           = "NumaConnect2 system",
 295        .probe                          = numachip2_probe,
 296        .acpi_madt_oem_check            = numachip2_acpi_madt_oem_check,
 297        .apic_id_valid                  = numachip_apic_id_valid,
 298        .apic_id_registered             = numachip_apic_id_registered,
 299
 300        .irq_delivery_mode              = dest_Fixed,
 301        .irq_dest_mode                  = 0, /* physical */
 302
 303        .target_cpus                    = online_target_cpus,
 304        .disable_esr                    = 0,
 305        .dest_logical                   = 0,
 306        .check_apicid_used              = NULL,
 307
 308        .vector_allocation_domain       = default_vector_allocation_domain,
 309        .init_apic_ldr                  = flat_init_apic_ldr,
 310
 311        .ioapic_phys_id_map             = NULL,
 312        .setup_apic_routing             = NULL,
 313        .cpu_present_to_apicid          = default_cpu_present_to_apicid,
 314        .apicid_to_cpu_present          = NULL,
 315        .check_phys_apicid_present      = default_check_phys_apicid_present,
 316        .phys_pkg_id                    = numachip_phys_pkg_id,
 317
 318        .get_apic_id                    = numachip2_get_apic_id,
 319        .set_apic_id                    = numachip2_set_apic_id,
 320
 321        .cpu_mask_to_apicid_and         = default_cpu_mask_to_apicid_and,
 322
 323        .send_IPI                       = numachip_send_IPI_one,
 324        .send_IPI_mask                  = numachip_send_IPI_mask,
 325        .send_IPI_mask_allbutself       = numachip_send_IPI_mask_allbutself,
 326        .send_IPI_allbutself            = numachip_send_IPI_allbutself,
 327        .send_IPI_all                   = numachip_send_IPI_all,
 328        .send_IPI_self                  = numachip_send_IPI_self,
 329
 330        .wakeup_secondary_cpu           = numachip_wakeup_secondary,
 331        .inquire_remote_apic            = NULL, /* REMRD not supported */
 332
 333        .read                           = native_apic_mem_read,
 334        .write                          = native_apic_mem_write,
 335        .eoi_write                      = native_apic_mem_write,
 336        .icr_read                       = native_apic_icr_read,
 337        .icr_write                      = native_apic_icr_write,
 338        .wait_icr_idle                  = numachip_apic_wait_icr_idle,
 339        .safe_wait_icr_idle             = numachip_safe_apic_wait_icr_idle,
 340};
 341
 342apic_driver(apic_numachip2);
 343