12ffd9e33SVitaly Kuznetsov #define pr_fmt(fmt) "Hyper-V: " fmt
22ffd9e33SVitaly Kuznetsov
32ffd9e33SVitaly Kuznetsov #include <linux/hyperv.h>
42ffd9e33SVitaly Kuznetsov #include <linux/log2.h>
52ffd9e33SVitaly Kuznetsov #include <linux/slab.h>
62ffd9e33SVitaly Kuznetsov #include <linux/types.h>
72ffd9e33SVitaly Kuznetsov
82ffd9e33SVitaly Kuznetsov #include <asm/fpu/api.h>
92ffd9e33SVitaly Kuznetsov #include <asm/mshyperv.h>
102ffd9e33SVitaly Kuznetsov #include <asm/msr.h>
112ffd9e33SVitaly Kuznetsov #include <asm/tlbflush.h>
1248a8b97cSPeter Zijlstra #include <asm/tlb.h>
132ffd9e33SVitaly Kuznetsov
14773b79f7SVitaly Kuznetsov #define CREATE_TRACE_POINTS
15773b79f7SVitaly Kuznetsov #include <asm/trace/hyperv.h>
16773b79f7SVitaly Kuznetsov
172ffd9e33SVitaly Kuznetsov /* Each gva in gva_list encodes up to 4096 pages to flush */
182ffd9e33SVitaly Kuznetsov #define HV_TLB_FLUSH_UNIT (4096 * PAGE_SIZE)
192ffd9e33SVitaly Kuznetsov
200e4c88f3SVitaly Kuznetsov static u64 hyperv_flush_tlb_others_ex(const struct cpumask *cpus,
210e4c88f3SVitaly Kuznetsov const struct flush_tlb_info *info);
22628f54ccSVitaly Kuznetsov
232ffd9e33SVitaly Kuznetsov /*
242ffd9e33SVitaly Kuznetsov * Fills in gva_list starting from offset. Returns the number of items added.
252ffd9e33SVitaly Kuznetsov */
fill_gva_list(u64 gva_list[],int offset,unsigned long start,unsigned long end)262ffd9e33SVitaly Kuznetsov static inline int fill_gva_list(u64 gva_list[], int offset,
272ffd9e33SVitaly Kuznetsov unsigned long start, unsigned long end)
282ffd9e33SVitaly Kuznetsov {
292ffd9e33SVitaly Kuznetsov int gva_n = offset;
302ffd9e33SVitaly Kuznetsov unsigned long cur = start, diff;
312ffd9e33SVitaly Kuznetsov
322ffd9e33SVitaly Kuznetsov do {
332ffd9e33SVitaly Kuznetsov diff = end > cur ? end - cur : 0;
342ffd9e33SVitaly Kuznetsov
352ffd9e33SVitaly Kuznetsov gva_list[gva_n] = cur & PAGE_MASK;
362ffd9e33SVitaly Kuznetsov /*
372ffd9e33SVitaly Kuznetsov * Lower 12 bits encode the number of additional
382ffd9e33SVitaly Kuznetsov * pages to flush (in addition to the 'cur' page).
392ffd9e33SVitaly Kuznetsov */
404030b4c5STianyu Lan if (diff >= HV_TLB_FLUSH_UNIT) {
412ffd9e33SVitaly Kuznetsov gva_list[gva_n] |= ~PAGE_MASK;
422ffd9e33SVitaly Kuznetsov cur += HV_TLB_FLUSH_UNIT;
434030b4c5STianyu Lan } else if (diff) {
444030b4c5STianyu Lan gva_list[gva_n] |= (diff - 1) >> PAGE_SHIFT;
454030b4c5STianyu Lan cur = end;
464030b4c5STianyu Lan }
474030b4c5STianyu Lan
482ffd9e33SVitaly Kuznetsov gva_n++;
492ffd9e33SVitaly Kuznetsov
502ffd9e33SVitaly Kuznetsov } while (cur < end);
512ffd9e33SVitaly Kuznetsov
522ffd9e33SVitaly Kuznetsov return gva_n - offset;
532ffd9e33SVitaly Kuznetsov }
542ffd9e33SVitaly Kuznetsov
cpu_is_lazy(int cpu)55493cc073SMichael Kelley static bool cpu_is_lazy(int cpu)
56493cc073SMichael Kelley {
57493cc073SMichael Kelley return per_cpu(cpu_tlbstate_shared.is_lazy, cpu);
58493cc073SMichael Kelley }
59493cc073SMichael Kelley
hyperv_flush_tlb_multi(const struct cpumask * cpus,const struct flush_tlb_info * info)604ce94eabSNadav Amit static void hyperv_flush_tlb_multi(const struct cpumask *cpus,
612ffd9e33SVitaly Kuznetsov const struct flush_tlb_info *info)
622ffd9e33SVitaly Kuznetsov {
632ffd9e33SVitaly Kuznetsov int cpu, vcpu, gva_n, max_gvas;
64c9c92beeSVitaly Kuznetsov struct hv_tlb_flush *flush;
65753ed9c9SJoseph Salisbury u64 status;
662ffd9e33SVitaly Kuznetsov unsigned long flags;
67493cc073SMichael Kelley bool do_lazy = !info->freed_tables;
682ffd9e33SVitaly Kuznetsov
694ce94eabSNadav Amit trace_hyperv_mmu_flush_tlb_multi(cpus, info);
70773b79f7SVitaly Kuznetsov
719a2d78e2SK. Y. Srinivasan if (!hv_hypercall_pg)
722ffd9e33SVitaly Kuznetsov goto do_native;
732ffd9e33SVitaly Kuznetsov
742ffd9e33SVitaly Kuznetsov local_irq_save(flags);
752ffd9e33SVitaly Kuznetsov
76*55e544e1SNischala Yelchuri flush = *this_cpu_ptr(hyperv_pcpu_input_arg);
7760d73a7cSVitaly Kuznetsov
7860d73a7cSVitaly Kuznetsov if (unlikely(!flush)) {
7960d73a7cSVitaly Kuznetsov local_irq_restore(flags);
8060d73a7cSVitaly Kuznetsov goto do_native;
8160d73a7cSVitaly Kuznetsov }
822ffd9e33SVitaly Kuznetsov
832ffd9e33SVitaly Kuznetsov if (info->mm) {
84617ab45cSVitaly Kuznetsov /*
85617ab45cSVitaly Kuznetsov * AddressSpace argument must match the CR3 with PCID bits
86617ab45cSVitaly Kuznetsov * stripped out.
87617ab45cSVitaly Kuznetsov */
882ffd9e33SVitaly Kuznetsov flush->address_space = virt_to_phys(info->mm->pgd);
89617ab45cSVitaly Kuznetsov flush->address_space &= CR3_ADDR_MASK;
902ffd9e33SVitaly Kuznetsov flush->flags = 0;
912ffd9e33SVitaly Kuznetsov } else {
922ffd9e33SVitaly Kuznetsov flush->address_space = 0;
932ffd9e33SVitaly Kuznetsov flush->flags = HV_FLUSH_ALL_VIRTUAL_ADDRESS_SPACES;
942ffd9e33SVitaly Kuznetsov }
952ffd9e33SVitaly Kuznetsov
962ffd9e33SVitaly Kuznetsov flush->processor_mask = 0;
972ffd9e33SVitaly Kuznetsov if (cpumask_equal(cpus, cpu_present_mask)) {
982ffd9e33SVitaly Kuznetsov flush->flags |= HV_FLUSH_ALL_PROCESSORS;
992ffd9e33SVitaly Kuznetsov } else {
1000e4c88f3SVitaly Kuznetsov /*
1010e4c88f3SVitaly Kuznetsov * From the supplied CPU set we need to figure out if we can get
1020e4c88f3SVitaly Kuznetsov * away with cheaper HVCALL_FLUSH_VIRTUAL_ADDRESS_{LIST,SPACE}
1030e4c88f3SVitaly Kuznetsov * hypercalls. This is possible when the highest VP number in
1040e4c88f3SVitaly Kuznetsov * the set is < 64. As VP numbers are usually in ascending order
1050e4c88f3SVitaly Kuznetsov * and match Linux CPU ids, here is an optimization: we check
1060e4c88f3SVitaly Kuznetsov * the VP number for the highest bit in the supplied set first
1070e4c88f3SVitaly Kuznetsov * so we can quickly find out if using *_EX hypercalls is a
1080e4c88f3SVitaly Kuznetsov * must. We will also check all VP numbers when walking the
1090e4c88f3SVitaly Kuznetsov * supplied CPU set to remain correct in all cases.
1100e4c88f3SVitaly Kuznetsov */
11151500b71SVitaly Kuznetsov cpu = cpumask_last(cpus);
11251500b71SVitaly Kuznetsov
11351500b71SVitaly Kuznetsov if (cpu < nr_cpumask_bits && hv_cpu_number_to_vp_number(cpu) >= 64)
1140e4c88f3SVitaly Kuznetsov goto do_ex_hypercall;
1150e4c88f3SVitaly Kuznetsov
1162ffd9e33SVitaly Kuznetsov for_each_cpu(cpu, cpus) {
117493cc073SMichael Kelley if (do_lazy && cpu_is_lazy(cpu))
118493cc073SMichael Kelley continue;
1192ffd9e33SVitaly Kuznetsov vcpu = hv_cpu_number_to_vp_number(cpu);
120110d2a7fSVitaly Kuznetsov if (vcpu == VP_INVAL) {
121110d2a7fSVitaly Kuznetsov local_irq_restore(flags);
122110d2a7fSVitaly Kuznetsov goto do_native;
123110d2a7fSVitaly Kuznetsov }
124110d2a7fSVitaly Kuznetsov
1252ffd9e33SVitaly Kuznetsov if (vcpu >= 64)
1260e4c88f3SVitaly Kuznetsov goto do_ex_hypercall;
1272ffd9e33SVitaly Kuznetsov
1282ffd9e33SVitaly Kuznetsov __set_bit(vcpu, (unsigned long *)
1292ffd9e33SVitaly Kuznetsov &flush->processor_mask);
1302ffd9e33SVitaly Kuznetsov }
13151500b71SVitaly Kuznetsov
13251500b71SVitaly Kuznetsov /* nothing to flush if 'processor_mask' ends up being empty */
13351500b71SVitaly Kuznetsov if (!flush->processor_mask) {
13451500b71SVitaly Kuznetsov local_irq_restore(flags);
13551500b71SVitaly Kuznetsov return;
13651500b71SVitaly Kuznetsov }
1372ffd9e33SVitaly Kuznetsov }
1382ffd9e33SVitaly Kuznetsov
1392ffd9e33SVitaly Kuznetsov /*
1402ffd9e33SVitaly Kuznetsov * We can flush not more than max_gvas with one hypercall. Flush the
1412ffd9e33SVitaly Kuznetsov * whole address space if we were asked to do more.
1422ffd9e33SVitaly Kuznetsov */
1432ffd9e33SVitaly Kuznetsov max_gvas = (PAGE_SIZE - sizeof(*flush)) / sizeof(flush->gva_list[0]);
1442ffd9e33SVitaly Kuznetsov
1452ffd9e33SVitaly Kuznetsov if (info->end == TLB_FLUSH_ALL) {
1462ffd9e33SVitaly Kuznetsov flush->flags |= HV_FLUSH_NON_GLOBAL_MAPPINGS_ONLY;
1472ffd9e33SVitaly Kuznetsov status = hv_do_hypercall(HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE,
1482ffd9e33SVitaly Kuznetsov flush, NULL);
1492ffd9e33SVitaly Kuznetsov } else if (info->end &&
1502ffd9e33SVitaly Kuznetsov ((info->end - info->start)/HV_TLB_FLUSH_UNIT) > max_gvas) {
1512ffd9e33SVitaly Kuznetsov status = hv_do_hypercall(HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE,
1522ffd9e33SVitaly Kuznetsov flush, NULL);
1532ffd9e33SVitaly Kuznetsov } else {
1542ffd9e33SVitaly Kuznetsov gva_n = fill_gva_list(flush->gva_list, 0,
1552ffd9e33SVitaly Kuznetsov info->start, info->end);
1562ffd9e33SVitaly Kuznetsov status = hv_do_rep_hypercall(HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST,
1572ffd9e33SVitaly Kuznetsov gva_n, 0, flush, NULL);
1582ffd9e33SVitaly Kuznetsov }
1590e4c88f3SVitaly Kuznetsov goto check_status;
1602ffd9e33SVitaly Kuznetsov
1610e4c88f3SVitaly Kuznetsov do_ex_hypercall:
1620e4c88f3SVitaly Kuznetsov status = hyperv_flush_tlb_others_ex(cpus, info);
1630e4c88f3SVitaly Kuznetsov
1640e4c88f3SVitaly Kuznetsov check_status:
1652ffd9e33SVitaly Kuznetsov local_irq_restore(flags);
1662ffd9e33SVitaly Kuznetsov
167753ed9c9SJoseph Salisbury if (hv_result_success(status))
1682ffd9e33SVitaly Kuznetsov return;
1692ffd9e33SVitaly Kuznetsov do_native:
1704ce94eabSNadav Amit native_flush_tlb_multi(cpus, info);
1712ffd9e33SVitaly Kuznetsov }
1722ffd9e33SVitaly Kuznetsov
hyperv_flush_tlb_others_ex(const struct cpumask * cpus,const struct flush_tlb_info * info)1730e4c88f3SVitaly Kuznetsov static u64 hyperv_flush_tlb_others_ex(const struct cpumask *cpus,
174628f54ccSVitaly Kuznetsov const struct flush_tlb_info *info)
175628f54ccSVitaly Kuznetsov {
176628f54ccSVitaly Kuznetsov int nr_bank = 0, max_gvas, gva_n;
177c9c92beeSVitaly Kuznetsov struct hv_tlb_flush_ex *flush;
1780e4c88f3SVitaly Kuznetsov u64 status;
179628f54ccSVitaly Kuznetsov
1800e4c88f3SVitaly Kuznetsov if (!(ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED))
181753ed9c9SJoseph Salisbury return HV_STATUS_INVALID_PARAMETER;
182628f54ccSVitaly Kuznetsov
183*55e544e1SNischala Yelchuri flush = *this_cpu_ptr(hyperv_pcpu_input_arg);
18460d73a7cSVitaly Kuznetsov
185628f54ccSVitaly Kuznetsov if (info->mm) {
186617ab45cSVitaly Kuznetsov /*
187617ab45cSVitaly Kuznetsov * AddressSpace argument must match the CR3 with PCID bits
188617ab45cSVitaly Kuznetsov * stripped out.
189617ab45cSVitaly Kuznetsov */
190628f54ccSVitaly Kuznetsov flush->address_space = virt_to_phys(info->mm->pgd);
191617ab45cSVitaly Kuznetsov flush->address_space &= CR3_ADDR_MASK;
192628f54ccSVitaly Kuznetsov flush->flags = 0;
193628f54ccSVitaly Kuznetsov } else {
194628f54ccSVitaly Kuznetsov flush->address_space = 0;
195628f54ccSVitaly Kuznetsov flush->flags = HV_FLUSH_ALL_VIRTUAL_ADDRESS_SPACES;
196628f54ccSVitaly Kuznetsov }
197628f54ccSVitaly Kuznetsov
198628f54ccSVitaly Kuznetsov flush->hv_vp_set.valid_bank_mask = 0;
199628f54ccSVitaly Kuznetsov
200366f03b0SK. Y. Srinivasan flush->hv_vp_set.format = HV_GENERIC_SET_SPARSE_4K;
201493cc073SMichael Kelley nr_bank = cpumask_to_vpset_skip(&flush->hv_vp_set, cpus,
202493cc073SMichael Kelley info->freed_tables ? NULL : cpu_is_lazy);
2030f0caa52SVitaly Kuznetsov if (nr_bank < 0)
204753ed9c9SJoseph Salisbury return HV_STATUS_INVALID_PARAMETER;
205628f54ccSVitaly Kuznetsov
206628f54ccSVitaly Kuznetsov /*
207628f54ccSVitaly Kuznetsov * We can flush not more than max_gvas with one hypercall. Flush the
208628f54ccSVitaly Kuznetsov * whole address space if we were asked to do more.
209628f54ccSVitaly Kuznetsov */
210628f54ccSVitaly Kuznetsov max_gvas =
211628f54ccSVitaly Kuznetsov (PAGE_SIZE - sizeof(*flush) - nr_bank *
212628f54ccSVitaly Kuznetsov sizeof(flush->hv_vp_set.bank_contents[0])) /
213628f54ccSVitaly Kuznetsov sizeof(flush->gva_list[0]);
214628f54ccSVitaly Kuznetsov
215628f54ccSVitaly Kuznetsov if (info->end == TLB_FLUSH_ALL) {
216628f54ccSVitaly Kuznetsov flush->flags |= HV_FLUSH_NON_GLOBAL_MAPPINGS_ONLY;
217628f54ccSVitaly Kuznetsov status = hv_do_rep_hypercall(
218628f54ccSVitaly Kuznetsov HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX,
219ab7ff471SMarcelo Henrique Cerri 0, nr_bank, flush, NULL);
220628f54ccSVitaly Kuznetsov } else if (info->end &&
221628f54ccSVitaly Kuznetsov ((info->end - info->start)/HV_TLB_FLUSH_UNIT) > max_gvas) {
222628f54ccSVitaly Kuznetsov status = hv_do_rep_hypercall(
223628f54ccSVitaly Kuznetsov HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX,
224ab7ff471SMarcelo Henrique Cerri 0, nr_bank, flush, NULL);
225628f54ccSVitaly Kuznetsov } else {
226628f54ccSVitaly Kuznetsov gva_n = fill_gva_list(flush->gva_list, nr_bank,
227628f54ccSVitaly Kuznetsov info->start, info->end);
228628f54ccSVitaly Kuznetsov status = hv_do_rep_hypercall(
229628f54ccSVitaly Kuznetsov HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST_EX,
230ab7ff471SMarcelo Henrique Cerri gva_n, nr_bank, flush, NULL);
231628f54ccSVitaly Kuznetsov }
232628f54ccSVitaly Kuznetsov
2330e4c88f3SVitaly Kuznetsov return status;
234628f54ccSVitaly Kuznetsov }
235628f54ccSVitaly Kuznetsov
hyperv_setup_mmu_ops(void)2362ffd9e33SVitaly Kuznetsov void hyperv_setup_mmu_ops(void)
2372ffd9e33SVitaly Kuznetsov {
238628f54ccSVitaly Kuznetsov if (!(ms_hyperv.hints & HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED))
239628f54ccSVitaly Kuznetsov return;
240628f54ccSVitaly Kuznetsov
2412ffd9e33SVitaly Kuznetsov pr_info("Using hypercall for remote TLB flush\n");
2424ce94eabSNadav Amit pv_ops.mmu.flush_tlb_multi = hyperv_flush_tlb_multi;
2435c83511bSJuergen Gross pv_ops.mmu.tlb_remove_table = tlb_remove_table;
2442ffd9e33SVitaly Kuznetsov }
245