Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 
0003 #include <linux/cpumask.h>
0004 #include <linux/acpi.h>
0005 
0006 #include "local.h"
0007 
0008 int x2apic_phys;
0009 
0010 static struct apic apic_x2apic_phys;
0011 static u32 x2apic_max_apicid __ro_after_init;
0012 
0013 void __init x2apic_set_max_apicid(u32 apicid)
0014 {
0015     x2apic_max_apicid = apicid;
0016 }
0017 
0018 static int __init set_x2apic_phys_mode(char *arg)
0019 {
0020     x2apic_phys = 1;
0021     return 0;
0022 }
0023 early_param("x2apic_phys", set_x2apic_phys_mode);
0024 
0025 static bool x2apic_fadt_phys(void)
0026 {
0027 #ifdef CONFIG_ACPI
0028     if ((acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID) &&
0029         (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL)) {
0030         printk(KERN_DEBUG "System requires x2apic physical mode\n");
0031         return true;
0032     }
0033 #endif
0034     return false;
0035 }
0036 
0037 static int x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
0038 {
0039     return x2apic_enabled() && (x2apic_phys || x2apic_fadt_phys());
0040 }
0041 
0042 static void x2apic_send_IPI(int cpu, int vector)
0043 {
0044     u32 dest = per_cpu(x86_cpu_to_apicid, cpu);
0045 
0046     /* x2apic MSRs are special and need a special fence: */
0047     weak_wrmsr_fence();
0048     __x2apic_send_IPI_dest(dest, vector, APIC_DEST_PHYSICAL);
0049 }
0050 
0051 static void
0052 __x2apic_send_IPI_mask(const struct cpumask *mask, int vector, int apic_dest)
0053 {
0054     unsigned long query_cpu;
0055     unsigned long this_cpu;
0056     unsigned long flags;
0057 
0058     /* x2apic MSRs are special and need a special fence: */
0059     weak_wrmsr_fence();
0060 
0061     local_irq_save(flags);
0062 
0063     this_cpu = smp_processor_id();
0064     for_each_cpu(query_cpu, mask) {
0065         if (apic_dest == APIC_DEST_ALLBUT && this_cpu == query_cpu)
0066             continue;
0067         __x2apic_send_IPI_dest(per_cpu(x86_cpu_to_apicid, query_cpu),
0068                        vector, APIC_DEST_PHYSICAL);
0069     }
0070     local_irq_restore(flags);
0071 }
0072 
0073 static void x2apic_send_IPI_mask(const struct cpumask *mask, int vector)
0074 {
0075     __x2apic_send_IPI_mask(mask, vector, APIC_DEST_ALLINC);
0076 }
0077 
0078 static void
0079  x2apic_send_IPI_mask_allbutself(const struct cpumask *mask, int vector)
0080 {
0081     __x2apic_send_IPI_mask(mask, vector, APIC_DEST_ALLBUT);
0082 }
0083 
0084 static void x2apic_send_IPI_allbutself(int vector)
0085 {
0086     __x2apic_send_IPI_shorthand(vector, APIC_DEST_ALLBUT);
0087 }
0088 
0089 static void x2apic_send_IPI_all(int vector)
0090 {
0091     __x2apic_send_IPI_shorthand(vector, APIC_DEST_ALLINC);
0092 }
0093 
0094 static void init_x2apic_ldr(void)
0095 {
0096 }
0097 
0098 static int x2apic_phys_probe(void)
0099 {
0100     if (x2apic_mode && (x2apic_phys || x2apic_fadt_phys()))
0101         return 1;
0102 
0103     return apic == &apic_x2apic_phys;
0104 }
0105 
0106 /* Common x2apic functions, also used by x2apic_cluster */
0107 int x2apic_apic_id_valid(u32 apicid)
0108 {
0109     if (x2apic_max_apicid && apicid > x2apic_max_apicid)
0110         return 0;
0111 
0112     return 1;
0113 }
0114 
0115 int x2apic_apic_id_registered(void)
0116 {
0117     return 1;
0118 }
0119 
0120 void __x2apic_send_IPI_dest(unsigned int apicid, int vector, unsigned int dest)
0121 {
0122     unsigned long cfg = __prepare_ICR(0, vector, dest);
0123     native_x2apic_icr_write(cfg, apicid);
0124 }
0125 
0126 void __x2apic_send_IPI_shorthand(int vector, u32 which)
0127 {
0128     unsigned long cfg = __prepare_ICR(which, vector, 0);
0129 
0130     /* x2apic MSRs are special and need a special fence: */
0131     weak_wrmsr_fence();
0132     native_x2apic_icr_write(cfg, 0);
0133 }
0134 
0135 unsigned int x2apic_get_apic_id(unsigned long id)
0136 {
0137     return id;
0138 }
0139 
0140 u32 x2apic_set_apic_id(unsigned int id)
0141 {
0142     return id;
0143 }
0144 
0145 int x2apic_phys_pkg_id(int initial_apicid, int index_msb)
0146 {
0147     return initial_apicid >> index_msb;
0148 }
0149 
0150 void x2apic_send_IPI_self(int vector)
0151 {
0152     apic_write(APIC_SELF_IPI, vector);
0153 }
0154 
0155 static struct apic apic_x2apic_phys __ro_after_init = {
0156 
0157     .name               = "physical x2apic",
0158     .probe              = x2apic_phys_probe,
0159     .acpi_madt_oem_check        = x2apic_acpi_madt_oem_check,
0160     .apic_id_valid          = x2apic_apic_id_valid,
0161     .apic_id_registered     = x2apic_apic_id_registered,
0162 
0163     .delivery_mode          = APIC_DELIVERY_MODE_FIXED,
0164     .dest_mode_logical      = false,
0165 
0166     .disable_esr            = 0,
0167 
0168     .check_apicid_used      = NULL,
0169     .init_apic_ldr          = init_x2apic_ldr,
0170     .ioapic_phys_id_map     = NULL,
0171     .setup_apic_routing     = NULL,
0172     .cpu_present_to_apicid      = default_cpu_present_to_apicid,
0173     .apicid_to_cpu_present      = NULL,
0174     .check_phys_apicid_present  = default_check_phys_apicid_present,
0175     .phys_pkg_id            = x2apic_phys_pkg_id,
0176 
0177     .get_apic_id            = x2apic_get_apic_id,
0178     .set_apic_id            = x2apic_set_apic_id,
0179 
0180     .calc_dest_apicid       = apic_default_calc_apicid,
0181 
0182     .send_IPI           = x2apic_send_IPI,
0183     .send_IPI_mask          = x2apic_send_IPI_mask,
0184     .send_IPI_mask_allbutself   = x2apic_send_IPI_mask_allbutself,
0185     .send_IPI_allbutself        = x2apic_send_IPI_allbutself,
0186     .send_IPI_all           = x2apic_send_IPI_all,
0187     .send_IPI_self          = x2apic_send_IPI_self,
0188 
0189     .inquire_remote_apic        = NULL,
0190 
0191     .read               = native_apic_msr_read,
0192     .write              = native_apic_msr_write,
0193     .eoi_write          = native_apic_msr_eoi_write,
0194     .icr_read           = native_x2apic_icr_read,
0195     .icr_write          = native_x2apic_icr_write,
0196     .wait_icr_idle          = native_x2apic_wait_icr_idle,
0197     .safe_wait_icr_idle     = native_safe_x2apic_wait_icr_idle,
0198 };
0199 
0200 apic_driver(apic_x2apic_phys);