linux/arch/x86/kernel/apic/x2apic_phys.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2
   3#include <linux/cpumask.h>
   4#include <linux/acpi.h>
   5
   6#include "local.h"
   7
   8int x2apic_phys;
   9
  10static struct apic apic_x2apic_phys;
  11static u32 x2apic_max_apicid __ro_after_init;
  12
  13void __init x2apic_set_max_apicid(u32 apicid)
  14{
  15        x2apic_max_apicid = apicid;
  16}
  17
  18static int __init set_x2apic_phys_mode(char *arg)
  19{
  20        x2apic_phys = 1;
  21        return 0;
  22}
  23early_param("x2apic_phys", set_x2apic_phys_mode);
  24
  25static bool x2apic_fadt_phys(void)
  26{
  27#ifdef CONFIG_ACPI
  28        if ((acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID) &&
  29                (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL)) {
  30                printk(KERN_DEBUG "System requires x2apic physical mode\n");
  31                return true;
  32        }
  33#endif
  34        return false;
  35}
  36
  37static int x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
  38{
  39        return x2apic_enabled() && (x2apic_phys || x2apic_fadt_phys());
  40}
  41
  42static void x2apic_send_IPI(int cpu, int vector)
  43{
  44        u32 dest = per_cpu(x86_cpu_to_apicid, cpu);
  45
  46        /* x2apic MSRs are special and need a special fence: */
  47        weak_wrmsr_fence();
  48        __x2apic_send_IPI_dest(dest, vector, APIC_DEST_PHYSICAL);
  49}
  50
  51static void
  52__x2apic_send_IPI_mask(const struct cpumask *mask, int vector, int apic_dest)
  53{
  54        unsigned long query_cpu;
  55        unsigned long this_cpu;
  56        unsigned long flags;
  57
  58        /* x2apic MSRs are special and need a special fence: */
  59        weak_wrmsr_fence();
  60
  61        local_irq_save(flags);
  62
  63        this_cpu = smp_processor_id();
  64        for_each_cpu(query_cpu, mask) {
  65                if (apic_dest == APIC_DEST_ALLBUT && this_cpu == query_cpu)
  66                        continue;
  67                __x2apic_send_IPI_dest(per_cpu(x86_cpu_to_apicid, query_cpu),
  68                                       vector, APIC_DEST_PHYSICAL);
  69        }
  70        local_irq_restore(flags);
  71}
  72
  73static void x2apic_send_IPI_mask(const struct cpumask *mask, int vector)
  74{
  75        __x2apic_send_IPI_mask(mask, vector, APIC_DEST_ALLINC);
  76}
  77
  78static void
  79 x2apic_send_IPI_mask_allbutself(const struct cpumask *mask, int vector)
  80{
  81        __x2apic_send_IPI_mask(mask, vector, APIC_DEST_ALLBUT);
  82}
  83
  84static void x2apic_send_IPI_allbutself(int vector)
  85{
  86        __x2apic_send_IPI_shorthand(vector, APIC_DEST_ALLBUT);
  87}
  88
  89static void x2apic_send_IPI_all(int vector)
  90{
  91        __x2apic_send_IPI_shorthand(vector, APIC_DEST_ALLINC);
  92}
  93
  94static void init_x2apic_ldr(void)
  95{
  96}
  97
  98static int x2apic_phys_probe(void)
  99{
 100        if (x2apic_mode && (x2apic_phys || x2apic_fadt_phys()))
 101                return 1;
 102
 103        return apic == &apic_x2apic_phys;
 104}
 105
 106/* Common x2apic functions, also used by x2apic_cluster */
 107int x2apic_apic_id_valid(u32 apicid)
 108{
 109        if (x2apic_max_apicid && apicid > x2apic_max_apicid)
 110                return 0;
 111
 112        return 1;
 113}
 114
 115int x2apic_apic_id_registered(void)
 116{
 117        return 1;
 118}
 119
 120void __x2apic_send_IPI_dest(unsigned int apicid, int vector, unsigned int dest)
 121{
 122        unsigned long cfg = __prepare_ICR(0, vector, dest);
 123        native_x2apic_icr_write(cfg, apicid);
 124}
 125
 126void __x2apic_send_IPI_shorthand(int vector, u32 which)
 127{
 128        unsigned long cfg = __prepare_ICR(which, vector, 0);
 129
 130        /* x2apic MSRs are special and need a special fence: */
 131        weak_wrmsr_fence();
 132        native_x2apic_icr_write(cfg, 0);
 133}
 134
 135unsigned int x2apic_get_apic_id(unsigned long id)
 136{
 137        return id;
 138}
 139
 140u32 x2apic_set_apic_id(unsigned int id)
 141{
 142        return id;
 143}
 144
 145int x2apic_phys_pkg_id(int initial_apicid, int index_msb)
 146{
 147        return initial_apicid >> index_msb;
 148}
 149
 150void x2apic_send_IPI_self(int vector)
 151{
 152        apic_write(APIC_SELF_IPI, vector);
 153}
 154
 155static struct apic apic_x2apic_phys __ro_after_init = {
 156
 157        .name                           = "physical x2apic",
 158        .probe                          = x2apic_phys_probe,
 159        .acpi_madt_oem_check            = x2apic_acpi_madt_oem_check,
 160        .apic_id_valid                  = x2apic_apic_id_valid,
 161        .apic_id_registered             = x2apic_apic_id_registered,
 162
 163        .delivery_mode                  = APIC_DELIVERY_MODE_FIXED,
 164        .dest_mode_logical              = false,
 165
 166        .disable_esr                    = 0,
 167
 168        .check_apicid_used              = NULL,
 169        .init_apic_ldr                  = init_x2apic_ldr,
 170        .ioapic_phys_id_map             = NULL,
 171        .setup_apic_routing             = NULL,
 172        .cpu_present_to_apicid          = default_cpu_present_to_apicid,
 173        .apicid_to_cpu_present          = NULL,
 174        .check_phys_apicid_present      = default_check_phys_apicid_present,
 175        .phys_pkg_id                    = x2apic_phys_pkg_id,
 176
 177        .get_apic_id                    = x2apic_get_apic_id,
 178        .set_apic_id                    = x2apic_set_apic_id,
 179
 180        .calc_dest_apicid               = apic_default_calc_apicid,
 181
 182        .send_IPI                       = x2apic_send_IPI,
 183        .send_IPI_mask                  = x2apic_send_IPI_mask,
 184        .send_IPI_mask_allbutself       = x2apic_send_IPI_mask_allbutself,
 185        .send_IPI_allbutself            = x2apic_send_IPI_allbutself,
 186        .send_IPI_all                   = x2apic_send_IPI_all,
 187        .send_IPI_self                  = x2apic_send_IPI_self,
 188
 189        .inquire_remote_apic            = NULL,
 190
 191        .read                           = native_apic_msr_read,
 192        .write                          = native_apic_msr_write,
 193        .eoi_write                      = native_apic_msr_eoi_write,
 194        .icr_read                       = native_x2apic_icr_read,
 195        .icr_write                      = native_x2apic_icr_write,
 196        .wait_icr_idle                  = native_x2apic_wait_icr_idle,
 197        .safe_wait_icr_idle             = native_safe_x2apic_wait_icr_idle,
 198};
 199
 200apic_driver(apic_x2apic_phys);
 201