linux/arch/x86/kernel/apic/x2apic_cluster.c
<<
>>
Prefs
   1#include <linux/threads.h>
   2#include <linux/cpumask.h>
   3#include <linux/string.h>
   4#include <linux/kernel.h>
   5#include <linux/ctype.h>
   6#include <linux/dmar.h>
   7#include <linux/cpu.h>
   8
   9#include <asm/smp.h>
  10#include <asm/x2apic.h>
  11
  12static DEFINE_PER_CPU(u32, x86_cpu_to_logical_apicid);
  13static DEFINE_PER_CPU(cpumask_var_t, cpus_in_cluster);
  14static DEFINE_PER_CPU(cpumask_var_t, ipi_mask);
  15
  16static int x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
  17{
  18        return x2apic_enabled();
  19}
  20
  21static inline u32 x2apic_cluster(int cpu)
  22{
  23        return per_cpu(x86_cpu_to_logical_apicid, cpu) >> 16;
  24}
  25
  26static void x2apic_send_IPI(int cpu, int vector)
  27{
  28        u32 dest = per_cpu(x86_cpu_to_logical_apicid, cpu);
  29
  30        x2apic_wrmsr_fence();
  31        __x2apic_send_IPI_dest(dest, vector, APIC_DEST_LOGICAL);
  32}
  33
  34static void
  35__x2apic_send_IPI_mask(const struct cpumask *mask, int vector, int apic_dest)
  36{
  37        struct cpumask *cpus_in_cluster_ptr;
  38        struct cpumask *ipi_mask_ptr;
  39        unsigned int cpu, this_cpu;
  40        unsigned long flags;
  41        u32 dest;
  42
  43        x2apic_wrmsr_fence();
  44
  45        local_irq_save(flags);
  46
  47        this_cpu = smp_processor_id();
  48
  49        /*
  50         * We are to modify mask, so we need an own copy
  51         * and be sure it's manipulated with irq off.
  52         */
  53        ipi_mask_ptr = this_cpu_cpumask_var_ptr(ipi_mask);
  54        cpumask_copy(ipi_mask_ptr, mask);
  55
  56        /*
  57         * The idea is to send one IPI per cluster.
  58         */
  59        for_each_cpu(cpu, ipi_mask_ptr) {
  60                unsigned long i;
  61
  62                cpus_in_cluster_ptr = per_cpu(cpus_in_cluster, cpu);
  63                dest = 0;
  64
  65                /* Collect cpus in cluster. */
  66                for_each_cpu_and(i, ipi_mask_ptr, cpus_in_cluster_ptr) {
  67                        if (apic_dest == APIC_DEST_ALLINC || i != this_cpu)
  68                                dest |= per_cpu(x86_cpu_to_logical_apicid, i);
  69                }
  70
  71                if (!dest)
  72                        continue;
  73
  74                __x2apic_send_IPI_dest(dest, vector, apic->dest_logical);
  75                /*
  76                 * Cluster sibling cpus should be discared now so
  77                 * we would not send IPI them second time.
  78                 */
  79                cpumask_andnot(ipi_mask_ptr, ipi_mask_ptr, cpus_in_cluster_ptr);
  80        }
  81
  82        local_irq_restore(flags);
  83}
  84
  85static void x2apic_send_IPI_mask(const struct cpumask *mask, int vector)
  86{
  87        __x2apic_send_IPI_mask(mask, vector, APIC_DEST_ALLINC);
  88}
  89
  90static void
  91x2apic_send_IPI_mask_allbutself(const struct cpumask *mask, int vector)
  92{
  93        __x2apic_send_IPI_mask(mask, vector, APIC_DEST_ALLBUT);
  94}
  95
  96static void x2apic_send_IPI_allbutself(int vector)
  97{
  98        __x2apic_send_IPI_mask(cpu_online_mask, vector, APIC_DEST_ALLBUT);
  99}
 100
 101static void x2apic_send_IPI_all(int vector)
 102{
 103        __x2apic_send_IPI_mask(cpu_online_mask, vector, APIC_DEST_ALLINC);
 104}
 105
 106static int
 107x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
 108                              const struct cpumask *andmask,
 109                              unsigned int *apicid)
 110{
 111        u32 dest = 0;
 112        u16 cluster;
 113        int i;
 114
 115        for_each_cpu_and(i, cpumask, andmask) {
 116                if (!cpumask_test_cpu(i, cpu_online_mask))
 117                        continue;
 118                dest = per_cpu(x86_cpu_to_logical_apicid, i);
 119                cluster = x2apic_cluster(i);
 120                break;
 121        }
 122
 123        if (!dest)
 124                return -EINVAL;
 125
 126        for_each_cpu_and(i, cpumask, andmask) {
 127                if (!cpumask_test_cpu(i, cpu_online_mask))
 128                        continue;
 129                if (cluster != x2apic_cluster(i))
 130                        continue;
 131                dest |= per_cpu(x86_cpu_to_logical_apicid, i);
 132        }
 133
 134        *apicid = dest;
 135
 136        return 0;
 137}
 138
 139static void init_x2apic_ldr(void)
 140{
 141        unsigned int this_cpu = smp_processor_id();
 142        unsigned int cpu;
 143
 144        per_cpu(x86_cpu_to_logical_apicid, this_cpu) = apic_read(APIC_LDR);
 145
 146        cpumask_set_cpu(this_cpu, per_cpu(cpus_in_cluster, this_cpu));
 147        for_each_online_cpu(cpu) {
 148                if (x2apic_cluster(this_cpu) != x2apic_cluster(cpu))
 149                        continue;
 150                cpumask_set_cpu(this_cpu, per_cpu(cpus_in_cluster, cpu));
 151                cpumask_set_cpu(cpu, per_cpu(cpus_in_cluster, this_cpu));
 152        }
 153}
 154
 155/*
 156 * At CPU state changes, update the x2apic cluster sibling info.
 157 */
 158static int x2apic_prepare_cpu(unsigned int cpu)
 159{
 160        if (!zalloc_cpumask_var(&per_cpu(cpus_in_cluster, cpu), GFP_KERNEL))
 161                return -ENOMEM;
 162
 163        if (!zalloc_cpumask_var(&per_cpu(ipi_mask, cpu), GFP_KERNEL)) {
 164                free_cpumask_var(per_cpu(cpus_in_cluster, cpu));
 165                return -ENOMEM;
 166        }
 167
 168        return 0;
 169}
 170
 171static int x2apic_dead_cpu(unsigned int this_cpu)
 172{
 173        int cpu;
 174
 175        for_each_online_cpu(cpu) {
 176                if (x2apic_cluster(this_cpu) != x2apic_cluster(cpu))
 177                        continue;
 178                cpumask_clear_cpu(this_cpu, per_cpu(cpus_in_cluster, cpu));
 179                cpumask_clear_cpu(cpu, per_cpu(cpus_in_cluster, this_cpu));
 180        }
 181        free_cpumask_var(per_cpu(cpus_in_cluster, this_cpu));
 182        free_cpumask_var(per_cpu(ipi_mask, this_cpu));
 183        return 0;
 184}
 185
 186static int x2apic_cluster_probe(void)
 187{
 188        int cpu = smp_processor_id();
 189        int ret;
 190
 191        if (!x2apic_mode)
 192                return 0;
 193
 194        ret = cpuhp_setup_state(CPUHP_X2APIC_PREPARE, "X2APIC_PREPARE",
 195                                x2apic_prepare_cpu, x2apic_dead_cpu);
 196        if (ret < 0) {
 197                pr_err("Failed to register X2APIC_PREPARE\n");
 198                return 0;
 199        }
 200        cpumask_set_cpu(cpu, per_cpu(cpus_in_cluster, cpu));
 201        return 1;
 202}
 203
 204static const struct cpumask *x2apic_cluster_target_cpus(void)
 205{
 206        return cpu_all_mask;
 207}
 208
 209/*
 210 * Each x2apic cluster is an allocation domain.
 211 */
 212static void cluster_vector_allocation_domain(int cpu, struct cpumask *retmask,
 213                                             const struct cpumask *mask)
 214{
 215        /*
 216         * To minimize vector pressure, default case of boot, device bringup
 217         * etc will use a single cpu for the interrupt destination.
 218         *
 219         * On explicit migration requests coming from irqbalance etc,
 220         * interrupts will be routed to the x2apic cluster (cluster-id
 221         * derived from the first cpu in the mask) members specified
 222         * in the mask.
 223         */
 224        if (mask == x2apic_cluster_target_cpus())
 225                cpumask_copy(retmask, cpumask_of(cpu));
 226        else
 227                cpumask_and(retmask, mask, per_cpu(cpus_in_cluster, cpu));
 228}
 229
 230static struct apic apic_x2apic_cluster __ro_after_init = {
 231
 232        .name                           = "cluster x2apic",
 233        .probe                          = x2apic_cluster_probe,
 234        .acpi_madt_oem_check            = x2apic_acpi_madt_oem_check,
 235        .apic_id_valid                  = x2apic_apic_id_valid,
 236        .apic_id_registered             = x2apic_apic_id_registered,
 237
 238        .irq_delivery_mode              = dest_LowestPrio,
 239        .irq_dest_mode                  = 1, /* logical */
 240
 241        .target_cpus                    = x2apic_cluster_target_cpus,
 242        .disable_esr                    = 0,
 243        .dest_logical                   = APIC_DEST_LOGICAL,
 244        .check_apicid_used              = NULL,
 245
 246        .vector_allocation_domain       = cluster_vector_allocation_domain,
 247        .init_apic_ldr                  = init_x2apic_ldr,
 248
 249        .ioapic_phys_id_map             = NULL,
 250        .setup_apic_routing             = NULL,
 251        .cpu_present_to_apicid          = default_cpu_present_to_apicid,
 252        .apicid_to_cpu_present          = NULL,
 253        .check_phys_apicid_present      = default_check_phys_apicid_present,
 254        .phys_pkg_id                    = x2apic_phys_pkg_id,
 255
 256        .get_apic_id                    = x2apic_get_apic_id,
 257        .set_apic_id                    = x2apic_set_apic_id,
 258
 259        .cpu_mask_to_apicid_and         = x2apic_cpu_mask_to_apicid_and,
 260
 261        .send_IPI                       = x2apic_send_IPI,
 262        .send_IPI_mask                  = x2apic_send_IPI_mask,
 263        .send_IPI_mask_allbutself       = x2apic_send_IPI_mask_allbutself,
 264        .send_IPI_allbutself            = x2apic_send_IPI_allbutself,
 265        .send_IPI_all                   = x2apic_send_IPI_all,
 266        .send_IPI_self                  = x2apic_send_IPI_self,
 267
 268        .inquire_remote_apic            = NULL,
 269
 270        .read                           = native_apic_msr_read,
 271        .write                          = native_apic_msr_write,
 272        .eoi_write                      = native_apic_msr_eoi_write,
 273        .icr_read                       = native_x2apic_icr_read,
 274        .icr_write                      = native_x2apic_icr_write,
 275        .wait_icr_idle                  = native_x2apic_wait_icr_idle,
 276        .safe_wait_icr_idle             = native_safe_x2apic_wait_icr_idle,
 277};
 278
 279apic_driver(apic_x2apic_cluster);
 280