On Tue, May 30, 2017 at 2:34 PM, Vitaly Kuznetsov <vkuznets@xxxxxxxxxx> wrote: > Hyper-V hosts may support more than 64 vCPUs, we need to use > HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX/LIST_EX hypercalls in this > case. > +/* HvFlushVirtualAddressSpaceEx, HvFlushVirtualAddressListEx hypercalls */ > +struct hv_flush_pcpu_ex { > + __u64 address_space; > + __u64 flags; > + struct { > + __u64 format; > + __u64 valid_bank_mask; > + __u64 bank_contents[]; > + } hv_vp_set; > + __u64 gva_list[]; > +}; Same question about use of uXX vs __uXX types. > +static void hyperv_flush_tlb_others_ex(const struct cpumask *cpus, > + struct mm_struct *mm, > + unsigned long start, > + unsigned long end) > +{ > + struct hv_flush_pcpu_ex *flush; > + unsigned long cur, flags; > + u64 status = U64_MAX; > + int nr_bank = 0, max_gvas, gva_n; > + > + if (!pcpu_flush_ex || !hv_hypercall_pg) > + goto do_native; > + > + if (cpumask_empty(cpus)) > + return; > + > + local_irq_save(flags); > + > + flush = this_cpu_ptr(pcpu_flush_ex); > + > + if (mm) { > + flush->address_space = virt_to_phys(mm->pgd); (u64), phys_addr_t is arch-dependent. > + flush->flags = 0; > + } else { > + flush->address_space = 0; > + flush->flags = HV_FLUSH_ALL_VIRTUAL_ADDRESS_SPACES; > + } > + > + flush->hv_vp_set.valid_bank_mask = 0; > + > + if (cpumask_equal(cpus, cpu_present_mask)) { > + flush->hv_vp_set.format = HV_GENERIC_SET_ALL; > + flush->flags |= HV_FLUSH_ALL_PROCESSORS; > + } else { > + flush->hv_vp_set.format = HV_GENERIC_SET_SPARCE_4K; > + nr_bank = cpumask_to_vp_set(flush, cpus); > + } > + > + /* > + * We can flush not more than max_gvas with one hypercall. Flush the > + * whole address space if we were asked to do more. > + */ > + max_gvas = (PAGE_SIZE - sizeof(*flush) - nr_bank*8) / 8; > + > + if (end == TLB_FLUSH_ALL) { > + flush->flags |= HV_FLUSH_NON_GLOBAL_MAPPINGS_ONLY; > + status = hv_do_rep_hypercall( > + HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX, > + 0, nr_bank + 2, flush, NULL); > + } else if (end && ((end - start)/HV_TLB_FLUSH_UNIT) > max_gvas) { > + status = hv_do_rep_hypercall( > + HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX, > + 0, nr_bank + 2, flush, NULL); > + } else { > + cur = start; > + gva_n = nr_bank; > + do { > + flush->gva_list[gva_n] = cur & PAGE_MASK; > + /* > + * Lower 12 bits encode the number of additional > + * pages to flush (in addition to the 'cur' page). > + */ > + if (end >= cur + HV_TLB_FLUSH_UNIT) > + flush->gva_list[gva_n] |= ~PAGE_MASK; > + else if (end > cur) > + flush->gva_list[gva_n] |= > + (end - cur - 1) >> PAGE_SHIFT; > + > + cur += HV_TLB_FLUSH_UNIT; > + ++gva_n; Same comments as per previous similar code. Moreover, since it's similar, can it have some common code shared? > + > + } while (cur < end); > + > + status = hv_do_rep_hypercall( > + HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST_EX, > + gva_n, nr_bank + 2, flush, NULL); > + } > + > + local_irq_restore(flags); > + > + if (!(status & 0xffff)) Magic. -- With Best Regards, Andy Shevchenko _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel