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/errno.h>
  15#include <linux/threads.h>
  16#include <linux/cpumask.h>
  17#include <linux/string.h>
  18#include <linux/kernel.h>
  19#include <linux/module.h>
  20#include <linux/ctype.h>
  21#include <linux/init.h>
  22#include <linux/hardirq.h>
  23#include <linux/delay.h>
  24
  25#include <asm/numachip/numachip.h>
  26#include <asm/numachip/numachip_csr.h>
  27#include <asm/smp.h>
  28#include <asm/apic.h>
  29#include <asm/ipi.h>
  30#include <asm/apic_flat_64.h>
  31#include <asm/pgtable.h>
  32
  33static int numachip_system __read_mostly;
  34
  35static const struct apic apic_numachip __read_mostly;
  36
  37static unsigned int get_apic_id(unsigned long x)
  38{
  39        unsigned long value;
  40        unsigned int id;
  41
  42        rdmsrl(MSR_FAM10H_NODE_ID, value);
  43        id = ((x >> 24) & 0xffU) | ((value << 2) & 0x3f00U);
  44
  45        return id;
  46}
  47
  48static unsigned long set_apic_id(unsigned int id)
  49{
  50        unsigned long x;
  51
  52        x = ((id & 0xffU) << 24);
  53        return x;
  54}
  55
  56static unsigned int read_xapic_id(void)
  57{
  58        return get_apic_id(apic_read(APIC_ID));
  59}
  60
  61static int numachip_apic_id_valid(int apicid)
  62{
  63        /* Trust what bootloader passes in MADT */
  64        return 1;
  65}
  66
  67static int numachip_apic_id_registered(void)
  68{
  69        return physid_isset(read_xapic_id(), phys_cpu_present_map);
  70}
  71
  72static int numachip_phys_pkg_id(int initial_apic_id, int index_msb)
  73{
  74        return initial_apic_id >> index_msb;
  75}
  76
  77static int __cpuinit numachip_wakeup_secondary(int phys_apicid, unsigned long start_rip)
  78{
  79        union numachip_csr_g3_ext_irq_gen int_gen;
  80
  81        int_gen.s._destination_apic_id = phys_apicid;
  82        int_gen.s._vector = 0;
  83        int_gen.s._msgtype = APIC_DM_INIT >> 8;
  84        int_gen.s._index = 0;
  85
  86        write_lcsr(CSR_G3_EXT_IRQ_GEN, int_gen.v);
  87
  88        int_gen.s._msgtype = APIC_DM_STARTUP >> 8;
  89        int_gen.s._vector = start_rip >> 12;
  90
  91        write_lcsr(CSR_G3_EXT_IRQ_GEN, int_gen.v);
  92
  93        atomic_set(&init_deasserted, 1);
  94        return 0;
  95}
  96
  97static void numachip_send_IPI_one(int cpu, int vector)
  98{
  99        union numachip_csr_g3_ext_irq_gen int_gen;
 100        int apicid = per_cpu(x86_cpu_to_apicid, cpu);
 101
 102        int_gen.s._destination_apic_id = apicid;
 103        int_gen.s._vector = vector;
 104        int_gen.s._msgtype = (vector == NMI_VECTOR ? APIC_DM_NMI : APIC_DM_FIXED) >> 8;
 105        int_gen.s._index = 0;
 106
 107        write_lcsr(CSR_G3_EXT_IRQ_GEN, int_gen.v);
 108}
 109
 110static void numachip_send_IPI_mask(const struct cpumask *mask, int vector)
 111{
 112        unsigned int cpu;
 113
 114        for_each_cpu(cpu, mask)
 115                numachip_send_IPI_one(cpu, vector);
 116}
 117
 118static void numachip_send_IPI_mask_allbutself(const struct cpumask *mask,
 119                                                int vector)
 120{
 121        unsigned int this_cpu = smp_processor_id();
 122        unsigned int cpu;
 123
 124        for_each_cpu(cpu, mask) {
 125                if (cpu != this_cpu)
 126                        numachip_send_IPI_one(cpu, vector);
 127        }
 128}
 129
 130static void numachip_send_IPI_allbutself(int vector)
 131{
 132        unsigned int this_cpu = smp_processor_id();
 133        unsigned int cpu;
 134
 135        for_each_online_cpu(cpu) {
 136                if (cpu != this_cpu)
 137                        numachip_send_IPI_one(cpu, vector);
 138        }
 139}
 140
 141static void numachip_send_IPI_all(int vector)
 142{
 143        numachip_send_IPI_mask(cpu_online_mask, vector);
 144}
 145
 146static void numachip_send_IPI_self(int vector)
 147{
 148        __default_send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL);
 149}
 150
 151static int __init numachip_probe(void)
 152{
 153        return apic == &apic_numachip;
 154}
 155
 156static void __init map_csrs(void)
 157{
 158        printk(KERN_INFO "NumaChip: Mapping local CSR space (%016llx - %016llx)\n",
 159                NUMACHIP_LCSR_BASE, NUMACHIP_LCSR_BASE + NUMACHIP_LCSR_SIZE - 1);
 160        init_extra_mapping_uc(NUMACHIP_LCSR_BASE, NUMACHIP_LCSR_SIZE);
 161
 162        printk(KERN_INFO "NumaChip: Mapping global CSR space (%016llx - %016llx)\n",
 163                NUMACHIP_GCSR_BASE, NUMACHIP_GCSR_BASE + NUMACHIP_GCSR_SIZE - 1);
 164        init_extra_mapping_uc(NUMACHIP_GCSR_BASE, NUMACHIP_GCSR_SIZE);
 165}
 166
 167static void fixup_cpu_id(struct cpuinfo_x86 *c, int node)
 168{
 169
 170        if (c->phys_proc_id != node) {
 171                c->phys_proc_id = node;
 172                per_cpu(cpu_llc_id, smp_processor_id()) = node;
 173        }
 174}
 175
 176static int __init numachip_system_init(void)
 177{
 178        unsigned int val;
 179
 180        if (!numachip_system)
 181                return 0;
 182
 183        x86_cpuinit.fixup_cpu_id = fixup_cpu_id;
 184        x86_init.pci.arch_init = pci_numachip_init;
 185
 186        map_csrs();
 187
 188        val = read_lcsr(CSR_G0_NODE_IDS);
 189        printk(KERN_INFO "NumaChip: Local NodeID = %08x\n", val);
 190
 191        return 0;
 192}
 193early_initcall(numachip_system_init);
 194
 195static int numachip_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
 196{
 197        if (!strncmp(oem_id, "NUMASC", 6)) {
 198                numachip_system = 1;
 199                return 1;
 200        }
 201
 202        return 0;
 203}
 204
 205static const struct apic apic_numachip __refconst = {
 206
 207        .name                           = "NumaConnect system",
 208        .probe                          = numachip_probe,
 209        .acpi_madt_oem_check            = numachip_acpi_madt_oem_check,
 210        .apic_id_valid                  = numachip_apic_id_valid,
 211        .apic_id_registered             = numachip_apic_id_registered,
 212
 213        .irq_delivery_mode              = dest_Fixed,
 214        .irq_dest_mode                  = 0, /* physical */
 215
 216        .target_cpus                    = online_target_cpus,
 217        .disable_esr                    = 0,
 218        .dest_logical                   = 0,
 219        .check_apicid_used              = NULL,
 220        .check_apicid_present           = NULL,
 221
 222        .vector_allocation_domain       = default_vector_allocation_domain,
 223        .init_apic_ldr                  = flat_init_apic_ldr,
 224
 225        .ioapic_phys_id_map             = NULL,
 226        .setup_apic_routing             = NULL,
 227        .multi_timer_check              = NULL,
 228        .cpu_present_to_apicid          = default_cpu_present_to_apicid,
 229        .apicid_to_cpu_present          = NULL,
 230        .setup_portio_remap             = NULL,
 231        .check_phys_apicid_present      = default_check_phys_apicid_present,
 232        .enable_apic_mode               = NULL,
 233        .phys_pkg_id                    = numachip_phys_pkg_id,
 234        .mps_oem_check                  = NULL,
 235
 236        .get_apic_id                    = get_apic_id,
 237        .set_apic_id                    = set_apic_id,
 238        .apic_id_mask                   = 0xffU << 24,
 239
 240        .cpu_mask_to_apicid_and         = default_cpu_mask_to_apicid_and,
 241
 242        .send_IPI_mask                  = numachip_send_IPI_mask,
 243        .send_IPI_mask_allbutself       = numachip_send_IPI_mask_allbutself,
 244        .send_IPI_allbutself            = numachip_send_IPI_allbutself,
 245        .send_IPI_all                   = numachip_send_IPI_all,
 246        .send_IPI_self                  = numachip_send_IPI_self,
 247
 248        .wakeup_secondary_cpu           = numachip_wakeup_secondary,
 249        .trampoline_phys_low            = DEFAULT_TRAMPOLINE_PHYS_LOW,
 250        .trampoline_phys_high           = DEFAULT_TRAMPOLINE_PHYS_HIGH,
 251        .wait_for_init_deassert         = NULL,
 252        .smp_callin_clear_local_apic    = NULL,
 253        .inquire_remote_apic            = NULL, /* REMRD not supported */
 254
 255        .read                           = native_apic_mem_read,
 256        .write                          = native_apic_mem_write,
 257        .eoi_write                      = native_apic_mem_write,
 258        .icr_read                       = native_apic_icr_read,
 259        .icr_write                      = native_apic_icr_write,
 260        .wait_icr_idle                  = native_apic_wait_icr_idle,
 261        .safe_wait_icr_idle             = native_safe_apic_wait_icr_idle,
 262};
 263apic_driver(apic_numachip);
 264
 265