0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #include <linux/types.h>
0023 #include <linux/vmalloc.h>
0024 #include <linux/mm.h>
0025 #include <linux/clockchips.h>
0026 #include <linux/hyperv.h>
0027 #include <linux/slab.h>
0028 #include <linux/cpuhotplug.h>
0029 #include <asm/hypervisor.h>
0030 #include <asm/mshyperv.h>
0031 #include <asm/apic.h>
0032
0033 #include <asm/trace/hyperv.h>
0034
0035 static struct apic orig_apic;
0036
0037 static u64 hv_apic_icr_read(void)
0038 {
0039 u64 reg_val;
0040
0041 rdmsrl(HV_X64_MSR_ICR, reg_val);
0042 return reg_val;
0043 }
0044
0045 static void hv_apic_icr_write(u32 low, u32 id)
0046 {
0047 u64 reg_val;
0048
0049 reg_val = SET_XAPIC_DEST_FIELD(id);
0050 reg_val = reg_val << 32;
0051 reg_val |= low;
0052
0053 wrmsrl(HV_X64_MSR_ICR, reg_val);
0054 }
0055
0056 static u32 hv_apic_read(u32 reg)
0057 {
0058 u32 reg_val, hi;
0059
0060 switch (reg) {
0061 case APIC_EOI:
0062 rdmsr(HV_X64_MSR_EOI, reg_val, hi);
0063 (void)hi;
0064 return reg_val;
0065 case APIC_TASKPRI:
0066 rdmsr(HV_X64_MSR_TPR, reg_val, hi);
0067 (void)hi;
0068 return reg_val;
0069
0070 default:
0071 return native_apic_mem_read(reg);
0072 }
0073 }
0074
0075 static void hv_apic_write(u32 reg, u32 val)
0076 {
0077 switch (reg) {
0078 case APIC_EOI:
0079 wrmsr(HV_X64_MSR_EOI, val, 0);
0080 break;
0081 case APIC_TASKPRI:
0082 wrmsr(HV_X64_MSR_TPR, val, 0);
0083 break;
0084 default:
0085 native_apic_mem_write(reg, val);
0086 }
0087 }
0088
0089 static void hv_apic_eoi_write(u32 reg, u32 val)
0090 {
0091 struct hv_vp_assist_page *hvp = hv_vp_assist_page[smp_processor_id()];
0092
0093 if (hvp && (xchg(&hvp->apic_assist, 0) & 0x1))
0094 return;
0095
0096 wrmsr(HV_X64_MSR_EOI, val, 0);
0097 }
0098
0099
0100
0101
0102 static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector,
0103 bool exclude_self)
0104 {
0105 struct hv_send_ipi_ex **arg;
0106 struct hv_send_ipi_ex *ipi_arg;
0107 unsigned long flags;
0108 int nr_bank = 0;
0109 u64 status = HV_STATUS_INVALID_PARAMETER;
0110
0111 if (!(ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED))
0112 return false;
0113
0114 local_irq_save(flags);
0115 arg = (struct hv_send_ipi_ex **)this_cpu_ptr(hyperv_pcpu_input_arg);
0116
0117 ipi_arg = *arg;
0118 if (unlikely(!ipi_arg))
0119 goto ipi_mask_ex_done;
0120
0121 ipi_arg->vector = vector;
0122 ipi_arg->reserved = 0;
0123 ipi_arg->vp_set.valid_bank_mask = 0;
0124
0125
0126
0127
0128
0129 if (!cpumask_equal(mask, cpu_present_mask) || exclude_self) {
0130 ipi_arg->vp_set.format = HV_GENERIC_SET_SPARSE_4K;
0131 if (exclude_self)
0132 nr_bank = cpumask_to_vpset_noself(&(ipi_arg->vp_set), mask);
0133 else
0134 nr_bank = cpumask_to_vpset(&(ipi_arg->vp_set), mask);
0135
0136
0137
0138
0139
0140
0141 if (nr_bank <= 0)
0142 goto ipi_mask_ex_done;
0143 } else {
0144 ipi_arg->vp_set.format = HV_GENERIC_SET_ALL;
0145 }
0146
0147 status = hv_do_rep_hypercall(HVCALL_SEND_IPI_EX, 0, nr_bank,
0148 ipi_arg, NULL);
0149
0150 ipi_mask_ex_done:
0151 local_irq_restore(flags);
0152 return hv_result_success(status);
0153 }
0154
0155 static bool __send_ipi_mask(const struct cpumask *mask, int vector,
0156 bool exclude_self)
0157 {
0158 int cur_cpu, vcpu, this_cpu = smp_processor_id();
0159 struct hv_send_ipi ipi_arg;
0160 u64 status;
0161 unsigned int weight;
0162
0163 trace_hyperv_send_ipi_mask(mask, vector);
0164
0165 weight = cpumask_weight(mask);
0166
0167
0168
0169
0170
0171
0172 if (weight == 0 ||
0173 (exclude_self && weight == 1 && cpumask_test_cpu(this_cpu, mask)))
0174 return true;
0175
0176 if (!hv_hypercall_pg)
0177 return false;
0178
0179 if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR))
0180 return false;
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192 if (hv_cpu_number_to_vp_number(cpumask_last(mask)) >= 64)
0193 goto do_ex_hypercall;
0194
0195 ipi_arg.vector = vector;
0196 ipi_arg.cpu_mask = 0;
0197
0198 for_each_cpu(cur_cpu, mask) {
0199 if (exclude_self && cur_cpu == this_cpu)
0200 continue;
0201 vcpu = hv_cpu_number_to_vp_number(cur_cpu);
0202 if (vcpu == VP_INVAL)
0203 return false;
0204
0205
0206
0207
0208
0209 if (vcpu >= 64)
0210 goto do_ex_hypercall;
0211
0212 __set_bit(vcpu, (unsigned long *)&ipi_arg.cpu_mask);
0213 }
0214
0215 status = hv_do_fast_hypercall16(HVCALL_SEND_IPI, ipi_arg.vector,
0216 ipi_arg.cpu_mask);
0217 return hv_result_success(status);
0218
0219 do_ex_hypercall:
0220 return __send_ipi_mask_ex(mask, vector, exclude_self);
0221 }
0222
0223 static bool __send_ipi_one(int cpu, int vector)
0224 {
0225 int vp = hv_cpu_number_to_vp_number(cpu);
0226 u64 status;
0227
0228 trace_hyperv_send_ipi_one(cpu, vector);
0229
0230 if (!hv_hypercall_pg || (vp == VP_INVAL))
0231 return false;
0232
0233 if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR))
0234 return false;
0235
0236 if (vp >= 64)
0237 return __send_ipi_mask_ex(cpumask_of(cpu), vector, false);
0238
0239 status = hv_do_fast_hypercall16(HVCALL_SEND_IPI, vector, BIT_ULL(vp));
0240 return hv_result_success(status);
0241 }
0242
0243 static void hv_send_ipi(int cpu, int vector)
0244 {
0245 if (!__send_ipi_one(cpu, vector))
0246 orig_apic.send_IPI(cpu, vector);
0247 }
0248
0249 static void hv_send_ipi_mask(const struct cpumask *mask, int vector)
0250 {
0251 if (!__send_ipi_mask(mask, vector, false))
0252 orig_apic.send_IPI_mask(mask, vector);
0253 }
0254
0255 static void hv_send_ipi_mask_allbutself(const struct cpumask *mask, int vector)
0256 {
0257 if (!__send_ipi_mask(mask, vector, true))
0258 orig_apic.send_IPI_mask_allbutself(mask, vector);
0259 }
0260
0261 static void hv_send_ipi_allbutself(int vector)
0262 {
0263 hv_send_ipi_mask_allbutself(cpu_online_mask, vector);
0264 }
0265
0266 static void hv_send_ipi_all(int vector)
0267 {
0268 if (!__send_ipi_mask(cpu_online_mask, vector, false))
0269 orig_apic.send_IPI_all(vector);
0270 }
0271
0272 static void hv_send_ipi_self(int vector)
0273 {
0274 if (!__send_ipi_one(smp_processor_id(), vector))
0275 orig_apic.send_IPI_self(vector);
0276 }
0277
0278 void __init hv_apic_init(void)
0279 {
0280 if (ms_hyperv.hints & HV_X64_CLUSTER_IPI_RECOMMENDED) {
0281 pr_info("Hyper-V: Using IPI hypercalls\n");
0282
0283
0284
0285 orig_apic = *apic;
0286
0287 apic->send_IPI = hv_send_ipi;
0288 apic->send_IPI_mask = hv_send_ipi_mask;
0289 apic->send_IPI_mask_allbutself = hv_send_ipi_mask_allbutself;
0290 apic->send_IPI_allbutself = hv_send_ipi_allbutself;
0291 apic->send_IPI_all = hv_send_ipi_all;
0292 apic->send_IPI_self = hv_send_ipi_self;
0293 }
0294
0295 if (ms_hyperv.hints & HV_X64_APIC_ACCESS_RECOMMENDED) {
0296 pr_info("Hyper-V: Using enlightened APIC (%s mode)",
0297 x2apic_enabled() ? "x2apic" : "xapic");
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309 apic_set_eoi_write(hv_apic_eoi_write);
0310 if (!x2apic_enabled()) {
0311 apic->read = hv_apic_read;
0312 apic->write = hv_apic_write;
0313 apic->icr_write = hv_apic_icr_write;
0314 apic->icr_read = hv_apic_icr_read;
0315 }
0316 }
0317 }