1 #include <linux/cpumask.h> 2 #include <linux/interrupt.h> 3 #include <linux/init.h> 4 5 #include <linux/mm.h> 6 #include <linux/delay.h> 7 #include <linux/spinlock.h> 8 #include <linux/kernel_stat.h> 9 #include <linux/mc146818rtc.h> 10 #include <linux/cache.h> 11 #include <linux/cpu.h> 12 #include <linux/module.h> 13 14 #include <asm/smp.h> 15 #include <asm/mtrr.h> 16 #include <asm/tlbflush.h> 17 #include <asm/mmu_context.h> 18 #include <asm/apic.h> 19 #include <asm/proto.h> 20 #include <asm/ipi.h> 21 22 void default_send_IPI_mask_sequence_phys(const struct cpumask *mask, int vector) 23 { 24 unsigned long query_cpu; 25 unsigned long flags; 26 27 /* 28 * Hack. The clustered APIC addressing mode doesn't allow us to send 29 * to an arbitrary mask, so I do a unicast to each CPU instead. 30 * - mbligh 31 */ 32 local_irq_save(flags); 33 for_each_cpu(query_cpu, mask) { 34 __default_send_IPI_dest_field(per_cpu(x86_cpu_to_apicid, 35 query_cpu), vector, APIC_DEST_PHYSICAL); 36 } 37 local_irq_restore(flags); 38 } 39 40 void default_send_IPI_mask_allbutself_phys(const struct cpumask *mask, 41 int vector) 42 { 43 unsigned int this_cpu = smp_processor_id(); 44 unsigned int query_cpu; 45 unsigned long flags; 46 47 /* See Hack comment above */ 48 49 local_irq_save(flags); 50 for_each_cpu(query_cpu, mask) { 51 if (query_cpu == this_cpu) 52 continue; 53 __default_send_IPI_dest_field(per_cpu(x86_cpu_to_apicid, 54 query_cpu), vector, APIC_DEST_PHYSICAL); 55 } 56 local_irq_restore(flags); 57 } 58 59 #ifdef CONFIG_X86_32 60 61 void default_send_IPI_mask_sequence_logical(const struct cpumask *mask, 62 int vector) 63 { 64 unsigned long flags; 65 unsigned int query_cpu; 66 67 /* 68 * Hack. The clustered APIC addressing mode doesn't allow us to send 69 * to an arbitrary mask, so I do a unicasts to each CPU instead. This 70 * should be modified to do 1 message per cluster ID - mbligh 71 */ 72 73 local_irq_save(flags); 74 for_each_cpu(query_cpu, mask) 75 __default_send_IPI_dest_field( 76 early_per_cpu(x86_cpu_to_logical_apicid, query_cpu), 77 vector, apic->dest_logical); 78 local_irq_restore(flags); 79 } 80 81 void default_send_IPI_mask_allbutself_logical(const struct cpumask *mask, 82 int vector) 83 { 84 unsigned long flags; 85 unsigned int query_cpu; 86 unsigned int this_cpu = smp_processor_id(); 87 88 /* See Hack comment above */ 89 90 local_irq_save(flags); 91 for_each_cpu(query_cpu, mask) { 92 if (query_cpu == this_cpu) 93 continue; 94 __default_send_IPI_dest_field( 95 early_per_cpu(x86_cpu_to_logical_apicid, query_cpu), 96 vector, apic->dest_logical); 97 } 98 local_irq_restore(flags); 99 } 100 101 /* 102 * This is only used on smaller machines. 103 */ 104 void default_send_IPI_mask_logical(const struct cpumask *cpumask, int vector) 105 { 106 unsigned long mask = cpumask_bits(cpumask)[0]; 107 unsigned long flags; 108 109 if (WARN_ONCE(!mask, "empty IPI mask")) 110 return; 111 112 local_irq_save(flags); 113 WARN_ON(mask & ~cpumask_bits(cpu_online_mask)[0]); 114 __default_send_IPI_dest_field(mask, vector, apic->dest_logical); 115 local_irq_restore(flags); 116 } 117 118 void default_send_IPI_allbutself(int vector) 119 { 120 /* 121 * if there are no other CPUs in the system then we get an APIC send 122 * error if we try to broadcast, thus avoid sending IPIs in this case. 123 */ 124 if (!(num_online_cpus() > 1)) 125 return; 126 127 __default_local_send_IPI_allbutself(vector); 128 } 129 130 void default_send_IPI_all(int vector) 131 { 132 __default_local_send_IPI_all(vector); 133 } 134 135 void default_send_IPI_self(int vector) 136 { 137 __default_send_IPI_shortcut(APIC_DEST_SELF, vector, apic->dest_logical); 138 } 139 140 /* must come after the send_IPI functions above for inlining */ 141 static int convert_apicid_to_cpu(int apic_id) 142 { 143 int i; 144 145 for_each_possible_cpu(i) { 146 if (per_cpu(x86_cpu_to_apicid, i) == apic_id) 147 return i; 148 } 149 return -1; 150 } 151 152 int safe_smp_processor_id(void) 153 { 154 int apicid, cpuid; 155 156 if (!cpu_has_apic) 157 return 0; 158 159 apicid = hard_smp_processor_id(); 160 if (apicid == BAD_APICID) 161 return 0; 162 163 cpuid = convert_apicid_to_cpu(apicid); 164 165 return cpuid >= 0 ? cpuid : 0; 166 } 167 #endif 168