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