X86/Hyper-V: Enhanced IPI enlightenment
[linux-2.6-block.git] / arch / x86 / include / asm / mshyperv.h
index 1eff91599c2b8afb704a3309a5a5c61bdbdda55b..0ee82519957be13c109f99fade8eda74025fc0a5 100644 (file)
@@ -259,6 +259,39 @@ static inline int hv_cpu_number_to_vp_number(int cpu_number)
        return hv_vp_index[cpu_number];
 }
 
+static inline int cpumask_to_vpset(struct hv_vpset *vpset,
+                                   const struct cpumask *cpus)
+{
+       int cpu, vcpu, vcpu_bank, vcpu_offset, nr_bank = 1;
+
+       /* valid_bank_mask can represent up to 64 banks */
+       if (hv_max_vp_index / 64 >= 64)
+               return 0;
+
+       /*
+        * Clear all banks up to the maximum possible bank as hv_flush_pcpu_ex
+        * structs are not cleared between calls, we risk flushing unneeded
+        * vCPUs otherwise.
+        */
+       for (vcpu_bank = 0; vcpu_bank <= hv_max_vp_index / 64; vcpu_bank++)
+               vpset->bank_contents[vcpu_bank] = 0;
+
+       /*
+        * Some banks may end up being empty but this is acceptable.
+        */
+       for_each_cpu(cpu, cpus) {
+               vcpu = hv_cpu_number_to_vp_number(cpu);
+               vcpu_bank = vcpu / 64;
+               vcpu_offset = vcpu % 64;
+               __set_bit(vcpu_offset, (unsigned long *)
+                         &vpset->bank_contents[vcpu_bank]);
+               if (vcpu_bank >= nr_bank)
+                       nr_bank = vcpu_bank + 1;
+       }
+       vpset->valid_bank_mask = GENMASK_ULL(nr_bank - 1, 0);
+       return nr_bank;
+}
+
 void __init hyperv_init(void);
 void hyperv_setup_mmu_ops(void);
 void hyper_alloc_mmu(void);