Re: [PATCH v5 09/10] x86/hyper-v: support extended CPU ranges for TLB flush hypercalls
From: Andy Shevchenko
Date: Tue May 30 2017 - 13:03:03 EST
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