1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <linux/cpumask.h> 4 #include <linux/acpi.h> 5 6 #include "local.h" 7 8 int x2apic_phys; 9 10 static struct apic apic_x2apic_phys; 11 u32 x2apic_max_apicid __ro_after_init = UINT_MAX; 12 13 void __init x2apic_set_max_apicid(u32 apicid) 14 { 15 x2apic_max_apicid = apicid; 16 if (apic->x2apic_set_max_apicid) 17 apic->max_apic_id = apicid; 18 } 19 20 static int __init set_x2apic_phys_mode(char *arg) 21 { 22 x2apic_phys = 1; 23 return 0; 24 } 25 early_param("x2apic_phys", set_x2apic_phys_mode); 26 27 static bool x2apic_fadt_phys(void) 28 { 29 #ifdef CONFIG_ACPI 30 if ((acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID) && 31 (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL)) { 32 printk(KERN_DEBUG "System requires x2apic physical mode\n"); 33 return true; 34 } 35 #endif 36 return false; 37 } 38 39 static int x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id) 40 { 41 return x2apic_enabled() && (x2apic_phys || x2apic_fadt_phys()); 42 } 43 44 static void x2apic_send_IPI(int cpu, int vector) 45 { 46 u32 dest = per_cpu(x86_cpu_to_apicid, cpu); 47 48 /* x2apic MSRs are special and need a special fence: */ 49 weak_wrmsr_fence(); 50 __x2apic_send_IPI_dest(dest, vector, APIC_DEST_PHYSICAL); 51 } 52 53 static void 54 __x2apic_send_IPI_mask(const struct cpumask *mask, int vector, int apic_dest) 55 { 56 unsigned long query_cpu; 57 unsigned long this_cpu; 58 unsigned long flags; 59 60 /* x2apic MSRs are special and need a special fence: */ 61 weak_wrmsr_fence(); 62 63 local_irq_save(flags); 64 65 this_cpu = smp_processor_id(); 66 for_each_cpu(query_cpu, mask) { 67 if (apic_dest == APIC_DEST_ALLBUT && this_cpu == query_cpu) 68 continue; 69 __x2apic_send_IPI_dest(per_cpu(x86_cpu_to_apicid, query_cpu), 70 vector, APIC_DEST_PHYSICAL); 71 } 72 local_irq_restore(flags); 73 } 74 75 static void x2apic_send_IPI_mask(const struct cpumask *mask, int vector) 76 { 77 __x2apic_send_IPI_mask(mask, vector, APIC_DEST_ALLINC); 78 } 79 80 static void 81 x2apic_send_IPI_mask_allbutself(const struct cpumask *mask, int vector) 82 { 83 __x2apic_send_IPI_mask(mask, vector, APIC_DEST_ALLBUT); 84 } 85 86 static void __x2apic_send_IPI_shorthand(int vector, u32 which) 87 { 88 unsigned long cfg = __prepare_ICR(which, vector, 0); 89 90 /* x2apic MSRs are special and need a special fence: */ 91 weak_wrmsr_fence(); 92 native_x2apic_icr_write(cfg, 0); 93 } 94 95 void x2apic_send_IPI_allbutself(int vector) 96 { 97 __x2apic_send_IPI_shorthand(vector, APIC_DEST_ALLBUT); 98 } 99 100 void x2apic_send_IPI_all(int vector) 101 { 102 __x2apic_send_IPI_shorthand(vector, APIC_DEST_ALLINC); 103 } 104 105 void x2apic_send_IPI_self(int vector) 106 { 107 apic_write(APIC_SELF_IPI, vector); 108 } 109 110 void __x2apic_send_IPI_dest(unsigned int apicid, int vector, unsigned int dest) 111 { 112 unsigned long cfg = __prepare_ICR(0, vector, dest); 113 native_x2apic_icr_write(cfg, apicid); 114 } 115 116 static int x2apic_phys_probe(void) 117 { 118 if (!x2apic_mode) 119 return 0; 120 121 if (x2apic_phys || x2apic_fadt_phys()) 122 return 1; 123 124 return apic == &apic_x2apic_phys; 125 } 126 127 u32 x2apic_get_apic_id(u32 id) 128 { 129 return id; 130 } 131 132 static struct apic apic_x2apic_phys __ro_after_init = { 133 134 .name = "physical x2apic", 135 .probe = x2apic_phys_probe, 136 .acpi_madt_oem_check = x2apic_acpi_madt_oem_check, 137 138 .dest_mode_logical = false, 139 140 .disable_esr = 0, 141 142 .cpu_present_to_apicid = default_cpu_present_to_apicid, 143 144 .max_apic_id = UINT_MAX, 145 .x2apic_set_max_apicid = true, 146 .get_apic_id = x2apic_get_apic_id, 147 148 .calc_dest_apicid = apic_default_calc_apicid, 149 150 .send_IPI = x2apic_send_IPI, 151 .send_IPI_mask = x2apic_send_IPI_mask, 152 .send_IPI_mask_allbutself = x2apic_send_IPI_mask_allbutself, 153 .send_IPI_allbutself = x2apic_send_IPI_allbutself, 154 .send_IPI_all = x2apic_send_IPI_all, 155 .send_IPI_self = x2apic_send_IPI_self, 156 .nmi_to_offline_cpu = true, 157 158 .read = native_apic_msr_read, 159 .write = native_apic_msr_write, 160 .eoi = native_apic_msr_eoi, 161 .icr_read = native_x2apic_icr_read, 162 .icr_write = native_x2apic_icr_write, 163 }; 164 165 apic_driver(apic_x2apic_phys); 166