Re: [Update PATCH] x86/Hyper-V: Initialize Syn timer clock when it's

2020-04-02 Thread Tianyu Lan

Hi Dan:
Sorry. Please ignore this patch and it's based on the old code.

On 4/2/2020 7:21 PM, Dan Carpenter wrote:

This doesn't apply to today's linux-next.

regards,
dan carpenter


___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH V2] x86/Hyper-V: don't allocate clockevent device when synthetic timer is unavailable

2020-03-31 Thread Tianyu Lan

On 3/31/2020 7:20 PM, Vitaly Kuznetsov wrote:

ltyker...@gmail.com writes:


From: Tianyu Lan 

Current code initializes clock event data structure for syn timer
even when it's unavailable. Fix it.

Signed-off-by: Tianyu Lan 
---
Change since v1:
Update title and commit log.

  drivers/hv/hv.c | 15 +--
  1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
index 632d25674e7f..2e893768fc76 100644
--- a/drivers/hv/hv.c
+++ b/drivers/hv/hv.c
@@ -212,13 +212,16 @@ int hv_synic_alloc(void)
tasklet_init(_cpu->msg_dpc,
 vmbus_on_msg_dpc, (unsigned long) hv_cpu);
  
-		hv_cpu->clk_evt = kzalloc(sizeof(struct clock_event_device),

- GFP_KERNEL);
-   if (hv_cpu->clk_evt == NULL) {
-   pr_err("Unable to allocate clock event device\n");
-   goto err;
+   if (ms_hyperv.features & HV_MSR_SYNTIMER_AVAILABLE) {
+   hv_cpu->clk_evt =
+   kzalloc(sizeof(struct clock_event_device),
+ GFP_KERNEL);
+   if (hv_cpu->clk_evt == NULL) {
+   pr_err("Unable to allocate clock event 
device\n");
+   goto err;
+   }
+   hv_init_clockevent_device(hv_cpu->clk_evt, cpu);
}
-   hv_init_clockevent_device(hv_cpu->clk_evt, cpu);
  
  		hv_cpu->synic_message_page =

(void *)get_zeroed_page(GFP_ATOMIC);


Thank you for fixing the subject! I had one more question on the
previous version which still stands: which tree is this patch for?
Upstream, clockevent allocation has moved to
drivers/clocksource/hyperv_timer.c and the code there is different.

Yes, I just noticed I fixed an issue on the old code after Michael 
reminded me. Sorry for noise. Please ignore it.


___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [Update PATCH] x86/Hyper-V: Initialize Syn timer clock when it's

2020-03-30 Thread Tianyu Lan

Hi Vitaly:
Thanks for your review.

On 3/30/2020 11:09 PM, Vitaly Kuznetsov wrote:

ltyker...@gmail.com writes:


From: Tianyu Lan 

Current code initializes clock event data structure for syn timer
even when it's not available. Fix it.

Signed-off-by: Tianyu Lan 
---
- Fix the wrong title.


The new one is ... weird too :-)

I think it was supposed to be something like "x86/Hyper-V: don't
allocate clockevent device when synthetic timer is unavailable"


Good suggestion. Will update in the next version.


  
  drivers/hv/hv.c | 15 +--


Which tree is this patch for? Upstream clockevent allocation has moved
to drivers/clocksource/hyperv_timer.c


  1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
index 632d25674e7f..2e893768fc76 100644
--- a/drivers/hv/hv.c
+++ b/drivers/hv/hv.c
@@ -212,13 +212,16 @@ int hv_synic_alloc(void)
tasklet_init(_cpu->msg_dpc,
 vmbus_on_msg_dpc, (unsigned long) hv_cpu);
  
-		hv_cpu->clk_evt = kzalloc(sizeof(struct clock_event_device),

- GFP_KERNEL);
-   if (hv_cpu->clk_evt == NULL) {
-   pr_err("Unable to allocate clock event device\n");
-   goto err;
+   if (ms_hyperv.features & HV_MSR_SYNTIMER_AVAILABLE) {
+   hv_cpu->clk_evt =
+   kzalloc(sizeof(struct clock_event_device),
+ GFP_KERNEL);
+   if (hv_cpu->clk_evt == NULL) {
+   pr_err("Unable to allocate clock event 
device\n");
+   goto err;
+   }
+   hv_init_clockevent_device(hv_cpu->clk_evt, cpu);
}
-   hv_init_clockevent_device(hv_cpu->clk_evt, cpu);
  
  		hv_cpu->synic_message_page =

(void *)get_zeroed_page(GFP_ATOMIC);



___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH] x86/Hyper-V: Initialize Syn timer clock even when it's not available

2020-03-30 Thread Tianyu Lan

Sorry for wrong title. Please ignore it.

On 3/30/2020 10:09 PM, ltyker...@gmail.com wrote:

From: Tianyu Lan 

Current code initializes clock event data structure for syn timer
even when it's available or not. Fix it.

Signed-off-by: Tianyu Lan 
---
  drivers/hv/hv.c | 15 +--
  1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
index 632d25674e7f..2e893768fc76 100644
--- a/drivers/hv/hv.c
+++ b/drivers/hv/hv.c
@@ -212,13 +212,16 @@ int hv_synic_alloc(void)
tasklet_init(_cpu->msg_dpc,
 vmbus_on_msg_dpc, (unsigned long) hv_cpu);
  
-		hv_cpu->clk_evt = kzalloc(sizeof(struct clock_event_device),

- GFP_KERNEL);
-   if (hv_cpu->clk_evt == NULL) {
-   pr_err("Unable to allocate clock event device\n");
-   goto err;
+   if (ms_hyperv.features & HV_MSR_SYNTIMER_AVAILABLE) {
+   hv_cpu->clk_evt =
+   kzalloc(sizeof(struct clock_event_device),
+ GFP_KERNEL);
+   if (hv_cpu->clk_evt == NULL) {
+   pr_err("Unable to allocate clock event 
device\n");
+   goto err;
+   }
+   hv_init_clockevent_device(hv_cpu->clk_evt, cpu);
}
-   hv_init_clockevent_device(hv_cpu->clk_evt, cpu);
  
  		hv_cpu->synic_message_page =

(void *)get_zeroed_page(GFP_ATOMIC);


___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [Resend PATCH V5 0/3] x86/Hyper-V/IOMMU: Add Hyper-V IOMMU driver to support x2apic mode

2019-02-26 Thread Tianyu Lan
On Tue, Feb 26, 2019 at 9:07 PM Joerg Roedel  wrote:
>
> On Tue, Feb 26, 2019 at 08:07:17PM +0800, lantianyu1...@gmail.com wrote:
> > Lan Tianyu (3):
> >   x86/Hyper-V: Set x2apic destination mode to physical when x2apic is
> >  available
> >   HYPERV/IOMMU: Add Hyper-V stub IOMMU driver
> >   MAINTAINERS: Add Hyper-V IOMMU driver into Hyper-V CORE AND DRIVERS
> > scope
>
> Applied (patch 2 with slight subject changes
> 'HYPERV/IOMMU' -> 'iommu/hyper-v'), thanks.

Great. Thanks.

-- 
Best regards
Tianyu Lan
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH V3 1/10] X86/Hyper-V: Add parameter offset for hyperv_fill_flush_guest_mapping_list()

2019-02-26 Thread Tianyu Lan
Hi Stephen:
   Thanks for your review.
On Sat, Feb 23, 2019 at 1:08 AM Stephen Hemminger
 wrote:
>
> int hyperv_fill_flush_guest_mapping_list(
> struct hv_guest_mapping_flush_list *flush,
> -   u64 start_gfn, u64 pages)
> +   int offset, u64 start_gfn, u64 pages)
>  {
> u64 cur = start_gfn;
> u64 additional_pages;
> -   int gpa_n = 0;
> +   int gpa_n = offset;
>
> do {
> /*
>
> Do you mean to support negative offsets here? Maybe unsigned would be better?

Yes, this makes sense. Will update. Thanks.

-- 
Best regards
Tianyu Lan
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [Update PATCH] x86/Hyper-V: Fix definition HV_MAX_FLUSH_REP_COUNT

2019-02-25 Thread Tianyu Lan
On Mon, Feb 25, 2019 at 10:19 PM Greg KH  wrote:
>
> On Mon, Feb 25, 2019 at 10:12:14PM +0800, lantianyu1...@gmail.com wrote:
> > From: Lan Tianyu 
> >
> > The max flush rep count of HvFlushGuestPhysicalAddressList hypercall
> > is equal with how many entries of union hv_gpa_page_range can be populated
> > into the input parameter page. The origin code lacks parenthesis around
> > PAGE_SIZE - 2 * sizeof(u64). This patch is to fix it.
> >
> > Cc: 
> > Fixs: cc4edae4b924 ("x86/hyper-v: Add HvFlushGuestAddressList hypercall 
> > support")
>
> "Fixes"

Sorry, fix this in the V2.
-- 
Best regards
Tianyu Lan
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH V3 00/10] X86/KVM/Hyper-V: Add HV ept tlb range list flush support in KVM

2019-02-23 Thread Tianyu Lan
On Sat, Feb 23, 2019 at 2:26 AM Paolo Bonzini  wrote:
>
> On 22/02/19 16:06, lantianyu1...@gmail.com wrote:
> > From: Lan Tianyu 
> >
> > This patchset is to introduce hv ept tlb range list flush function
> > support in the KVM MMU component. Flushing ept tlbs of several address
> > range can be done via single hypercall and new list flush function is
> > used in the kvm_mmu_commit_zap_page() and FNAME(sync_page). This patchset
> > also adds more hv ept tlb range flush support in more KVM MMU function.
> >
> > This patchset is based on the fix patch "x86/Hyper-V: Fix definition 
> > HV_MAX_FLUSH_REP_COUNT".
> > (https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1939455.html)
>
> Note that this won't make it in 5.1 unless Linus releases an -rc8.
> Otherwise, I'll get to it next week.
Hi Paolo:
  Sure. Thanks for your review.

-- 
Best regards
Tianyu Lan
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH] x86/Hyper-V: Fix definition HV_MAX_FLUSH_REP_COUNT

2019-02-23 Thread Tianyu Lan
On Fri, Feb 22, 2019 at 10:32 PM Greg KH  wrote:
>
> On Fri, Feb 22, 2019 at 06:48:44PM +0800, lantianyu1...@gmail.com wrote:
> > From: Lan Tianyu 
> >
> > The max flush rep count of HvFlushGuestPhysicalAddressList hypercall
> > is equal with how many entries of union hv_gpa_page_range can be populated
> > into the input parameter page. The origin code lacks parenthesis around
> > PAGE_SIZE - 2 * sizeof(u64). This patch is to fix it.
> >
> > Cc: 
> > Fixs: cc4edae4b9(x86/hyper-v: Add HvFlushGuestAddressList hypercall support)
>
> Please use this format instead:
>
> Fixes: cc4edae4b924 ("x86/hyper-v: Add HvFlushGuestAddressList hypercall 
> support")
>
> And don't type it by hand, use a git alias for it:
> git show -s --abbrev-commit --abbrev=12 --pretty=format:"%h 
> (\"%s\")%n"
>

OK. Will update. Thanks.

> You also messed up your To: line, keeping anyone from being able to
> respond to this message who do not know how to hand-edit the response
> line :(

I put all expected reviewers in the Cc line and will put into To line.

>
> thanks,
>
> greg k-h



-- 
Best regards
Tianyu Lan
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 1/3] x86/Hyper-V: Set x2apic destination mode to physical when x2apic is available

2019-01-31 Thread Tianyu Lan
On Fri, Feb 1, 2019 at 3:07 PM Dan Carpenter  wrote:
>
> On Thu, Jan 31, 2019 at 06:17:31PM +0800, lantianyu1...@gmail.com wrote:
> >
> >
>
> This comment needs to be indented one tab or it looks like we're outside
> the funciton.
>
> > +/*
> > + * Hyper-V doesn't provide irq remapping for IO-APIC. To enable x2apic,
> > + * set x2apic destination mode to physcial mode when x2apic is available
> > + * and Hyper-V IOMMU driver makes sure cpus assigned with IO-APIC irqs
> > + * have 8-bit APIC id.
> > + */
> > +# if IS_ENABLED(CONFIG_HYPERV_IOMMU)
> > + if (x2apic_supported())
> > + x2apic_phys = 1;
> > +# endif
>
> The IS_ENABLED() macro is really magical.  You could write this like so:
>
> if (IS_ENABLED(CONFIG_HYPERV_IOMMU) && x2apic_supported())
> x2apic_phys = 1;
>
> It works the same and is slightly more pleasant to look at.

Yes, that will better. Thanks for your suggestion. Dan

-- 
Best regards
Tianyu Lan
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 1/3] x86/Hyper-V: Set x2apic destination mode to physical when x2apic is available

2019-01-31 Thread Tianyu Lan
Hi Greg:
 Thanks for your review.

On Thu, Jan 31, 2019 at 7:57 PM Greg KH  wrote:
>
> On Thu, Jan 31, 2019 at 06:17:31PM +0800, lantianyu1...@gmail.com wrote:
> > From: Lan Tianyu 
> >
> > Hyper-V doesn't provide irq remapping for IO-APIC. To enable x2apic,
> > set x2apic destination mode to physcial mode when x2apic is available
> > and Hyper-V IOMMU driver makes sure cpus assigned with IO-APIC irqs have
> > 8-bit APIC id.
> >
> > Signed-off-by: Lan Tianyu 
> > ---
> >  arch/x86/kernel/cpu/mshyperv.c | 14 ++
> >  1 file changed, 14 insertions(+)
> >
> > diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
> > index e81a2db..9d62f33 100644
> > --- a/arch/x86/kernel/cpu/mshyperv.c
> > +++ b/arch/x86/kernel/cpu/mshyperv.c
> > @@ -36,6 +36,8 @@
> >  struct ms_hyperv_info ms_hyperv;
> >  EXPORT_SYMBOL_GPL(ms_hyperv);
> >
> > +extern int x2apic_phys;
>
> Shouldn't this be in a .h file somewhere instead?

You are right. I should use  here. Thanks.

> thanks,
>
> greg k-h



-- 
Best regards
Tianyu Lan
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH V5 00/10] x86/KVM/Hyper-v: Add HV ept tlb range flush hypercall support in KVM

2018-11-27 Thread Tianyu Lan
On Tue, Nov 27, 2018 at 8:12 PM Dan Carpenter  wrote:
>
> On Tue, Nov 27, 2018 at 07:59:22PM +0800, Tianyu Lan wrote:
> > Gentile Ping...
> >
> > On Thu, Nov 8, 2018 at 10:43 PM  wrote:
> > >
> > > From: Lan Tianyu 
> > >
> > > Sorry. Some patches was blocked and I try to resend via another account.
>
> The patches were still blocked?  They didn't show up on driver-devel.
>
> regards,
> dan carpenter
>

Hi Dan:
Thanks for reminder. I double check kvm maillist archive
and this series is available.
https://marc.info/?l=kvm=154168821118117=2

-- 
Best regards
Tianyu Lan
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH V5 00/10] x86/KVM/Hyper-v: Add HV ept tlb range flush hypercall support in KVM

2018-11-27 Thread Tianyu Lan
Gentile Ping...

On Thu, Nov 8, 2018 at 10:43 PM  wrote:
>
> From: Lan Tianyu 
>
> Sorry. Some patches was blocked and I try to resend via another account.
>
> For nested memory virtualization, Hyper-v doesn't set write-protect
> L1 hypervisor EPT page directory and page table node to track changes
> while it relies on guest to tell it changes via HvFlushGuestAddressLlist
> hypercall. HvFlushGuestAddressLlist hypercall provides a way to flush
> EPT page table with ranges which are specified by L1 hypervisor.
>
> If L1 hypervisor uses INVEPT or HvFlushGuestAddressSpace hypercall to
> flush EPT tlb, Hyper-V will invalidate associated EPT shadow page table
> and sync L1's EPT table when next EPT page fault is triggered.
> HvFlushGuestAddressLlist hypercall helps to avoid such redundant EPT
> page fault and synchronization of shadow page table.
>
> This patchset is rebased on the Linux 4.20-rc1 and Patch "KVM/VMX: Check
> ept_pointer before flushing ept tlb".(https://www.mail-archive.com/linux
> -ker...@vger.kernel.org/msg1798827.html).
>
> Change since v4:
>1) Split flush address and flush list patches. This patchset only 
> contains
>flush address patches. Will post flush list patches later.
>2) Expose function hyperv_fill_flush_guest_mapping_list()
>out of hyperv file
>3) Adjust parameter of hyperv_flush_guest_mapping_range()
>4) Reorder patchset and move Hyper-V and VMX changes ahead.
>
> Change since v3:
> 1) Remove code of updating "tlbs_dirty" in 
> kvm_flush_remote_tlbs_with_range()
> 2) Remove directly tlb flush in the kvm_handle_hva_range()
> 3) Move tlb flush in kvm_set_pte_rmapp() to 
> kvm_mmu_notifier_change_pte()
> 4) Combine Vitaly's "don't pass EPT configuration info to
> vmx_hv_remote_flush_tlb()" fix
>
> Change since v2:
>1) Fix comment in the kvm_flush_remote_tlbs_with_range()
>2) Move HV_MAX_FLUSH_PAGES and HV_MAX_FLUSH_REP_COUNT to
> hyperv-tlfs.h.
>3) Calculate HV_MAX_FLUSH_REP_COUNT in the macro definition
>4) Use HV_MAX_FLUSH_REP_COUNT to define length of gpa_list in
> struct hv_guest_mapping_flush_list.
>
> Change since v1:
>1) Convert "end_gfn" of struct kvm_tlb_range to "pages" in order
>   to avoid confusion as to whether "end_gfn" is inclusive or exlusive.
>2) Add hyperv tlb range struct and replace kvm tlb range struct
>   with new struct in order to avoid using kvm struct in the hyperv
>   code directly.
>
>
> Lan Tianyu (10):
>   KVM: Add tlb_remote_flush_with_range callback in kvm_x86_ops
>   x86/hyper-v: Add HvFlushGuestAddressList hypercall support
>   x86/Hyper-v: Add trace in the
> hyperv_nested_flush_guest_mapping_range()
>   KVM/VMX: Add hv tlb range flush support
>   KVM/MMU: Add tlb flush with range helper function
>   KVM: Replace old tlb flush function with new one to flush a specified
> range.
>   KVM: Make kvm_set_spte_hva() return int
>   KVM/MMU: Move tlb flush in kvm_set_pte_rmapp() to
> kvm_mmu_notifier_change_pte()
>   KVM/MMU: Flush tlb directly in the kvm_set_pte_rmapp()
>   KVM/MMU: Flush tlb directly in the kvm_zap_gfn_range()
>
>  arch/arm/include/asm/kvm_host.h |  2 +-
>  arch/arm64/include/asm/kvm_host.h   |  2 +-
>  arch/mips/include/asm/kvm_host.h|  2 +-
>  arch/mips/kvm/mmu.c |  3 +-
>  arch/powerpc/include/asm/kvm_host.h |  2 +-
>  arch/powerpc/kvm/book3s.c   |  3 +-
>  arch/powerpc/kvm/e500_mmu_host.c|  3 +-
>  arch/x86/hyperv/nested.c| 80 +++
>  arch/x86/include/asm/hyperv-tlfs.h  | 32 +
>  arch/x86/include/asm/kvm_host.h |  9 +++-
>  arch/x86/include/asm/mshyperv.h | 15 ++
>  arch/x86/include/asm/trace/hyperv.h | 14 ++
>  arch/x86/kvm/mmu.c  | 96 
> +----
>  arch/x86/kvm/paging_tmpl.h  |  3 +-
>  arch/x86/kvm/vmx.c  | 69 ++
>  virt/kvm/arm/mmu.c  |  6 ++-
>  virt/kvm/kvm_main.c |  5 +-
>  17 files changed, 295 insertions(+), 51 deletions(-)
>
> --
> 2.14.4
>


-- 
Best regards
Tianyu Lan
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH V4 7/15] KVM/MMU: Flush tlb directly in the kvm_zap_gfn_range()

2018-10-15 Thread Tianyu Lan
Hi Paolo:
  Thanks for your review.

On Mon, Oct 15, 2018 at 6:04 PM Paolo Bonzini  wrote:
>
> On 13/10/2018 16:53, lantianyu1...@gmail.com wrote:
> > + bool flush = false;
> >   int i;
> >
> >   spin_lock(>mmu_lock);
> > @@ -5654,18 +5655,27 @@ void kvm_zap_gfn_range(struct kvm *kvm, gfn_t 
> > gfn_start, gfn_t gfn_end)
> >   slots = __kvm_memslots(kvm, i);
> >   kvm_for_each_memslot(memslot, slots) {
> >   gfn_t start, end;
> > + bool flush_tlb = true;
> >
> >   start = max(gfn_start, memslot->base_gfn);
> >   end = min(gfn_end, memslot->base_gfn + 
> > memslot->npages);
> >   if (start >= end)
> >   continue;
> >
> > - slot_handle_level_range(kvm, memslot, kvm_zap_rmapp,
> > - PT_PAGE_TABLE_LEVEL, 
> > PT_MAX_HUGEPAGE_LEVEL,
> > - start, end - 1, true);
> > + if (kvm_available_flush_tlb_with_range())
> > + flush_tlb = false;
>
> This should be moved outside the for, because it's invariant.
>
> > + flush = slot_handle_level_range(kvm, memslot,
> > + kvm_zap_rmapp, PT_PAGE_TABLE_LEVEL,
> > + PT_MAX_HUGEPAGE_LEVEL, start,
> > + end - 1, flush_tlb);
>
> ... and this should be "flush |= ".
> >   }
> >   }
> >
> > + if (flush && kvm_available_flush_tlb_with_range())
> > + kvm_flush_remote_tlbs_with_address(kvm, gfn_start,
> > + gfn_end - gfn_start + 1);
> > +
>
> ... and this can be just if (flush), because if flush_tlb is true then
> slot_handle_level_range always returns false.

OK. Will update.

-- 
Best regards
Tianyu Lan
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH V4 2/15] KVM/MMU: Add tlb flush with range helper function

2018-10-14 Thread Tianyu Lan
Hi Russell:
  Thanks for your review.

On Sun, Oct 14, 2018 at 5:36 PM Russell King - ARM Linux
 wrote:
>
> On Sun, Oct 14, 2018 at 10:27:34AM +0100, Russell King - ARM Linux wrote:
> > On Sun, Oct 14, 2018 at 10:16:56AM +0200, Thomas Gleixner wrote:
> > > On Sun, 14 Oct 2018, Liran Alon wrote:
> > > > > On 13 Oct 2018, at 17:53, lantianyu1...@gmail.com wrote:
> > > > >
> > > > > From: Lan Tianyu 
> > > > >
> > > > > This patch is to add wrapper functions for tlb_remote_flush_with_range
> > > > > callback.
> > > > >
> > > > > Signed-off-by: Lan Tianyu 
> > > > > ---
> > > > > Change sicne V3:
> > > > >   Remove code of updating "tlbs_dirty"
> > > > > Change since V2:
> > > > >   Fix comment in the kvm_flush_remote_tlbs_with_range()
> > > > > ---
> > > > > arch/x86/kvm/mmu.c | 40 
> > > > > 1 file changed, 40 insertions(+)
> > > > >
> > > > > diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
> > > > > index c73d9f650de7..ff656d85903a 100644
> > > > > --- a/arch/x86/kvm/mmu.c
> > > > > +++ b/arch/x86/kvm/mmu.c
> > > > > @@ -264,6 +264,46 @@ static void mmu_spte_set(u64 *sptep, u64 spte);
> > > > > static union kvm_mmu_page_role
> > > > > kvm_mmu_calc_root_page_role(struct kvm_vcpu *vcpu);
> > > > >
> > > > > +
> > > > > +static inline bool kvm_available_flush_tlb_with_range(void)
> > > > > +{
> > > > > +   return kvm_x86_ops->tlb_remote_flush_with_range;
> > > > > +}
> > > >
> > > > Seems that kvm_available_flush_tlb_with_range() is not used in this 
> > > > patch…
> > >
> > > What's wrong with that?
> > >
> > > It provides the implementation and later patches make use of it. It's a
> > > sensible way to split patches into small, self contained entities.
> >
> > From what I can see of the patches that follow _this_ patch in the
> > series, this function remains unused.  So, not only is it not used
> > in this patch, it's not used in this series.
>
> Note - I seem to have only received patches 1 through 4, so this is
> based on the patches I've received.
>

Sorry to confuse your. I get from CCers from get_maintainer.pl script.
The next patch "[PATCH V4 3/15]KVM: Replace old tlb flush function with
new one to flush a specified range" calls new function.
https://lkml.org/lkml/2018/10/13/254

The patch "[PATCH V4 4/15] KVM: Make kvm_set_spte_hva() return int"
changes under ARM directory. Please have a look. Thanks.
-- 
Best regards
Tianyu Lan
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH V4 2/15] KVM/MMU: Add tlb flush with range helper function

2018-10-14 Thread Tianyu Lan
Hi Liran & Thomas:
  Thanks for your review.


On Sun, Oct 14, 2018 at 5:20 PM Liran Alon  wrote:
>
>
>
> > On 14 Oct 2018, at 11:16, Thomas Gleixner  wrote:
> >
> > On Sun, 14 Oct 2018, Liran Alon wrote:
> >>> On 13 Oct 2018, at 17:53, lantianyu1...@gmail.com wrote:
> >>>
> >>> +
> >>> +static inline bool kvm_available_flush_tlb_with_range(void)
> >>> +{
> >>> +   return kvm_x86_ops->tlb_remote_flush_with_range;
> >>> +}
> >>
> >> Seems that kvm_available_flush_tlb_with_range() is not used in this patch…
> >
> > What's wrong with that?
> >
> > It provides the implementation and later patches make use of it. It's a
> > sensible way to split patches into small, self contained entities.
> >
> > Thanks,
> >
> >   tglx
> >
>
> I guess it’s a matter of taste, but I prefer to not add dead-code for patches
> in order for each commit to compile nicely without warnings of declared and 
> unused functions.
> I would prefer to just add this utility function on the patch that actually 
> use it.
>
> -Liran
>

Normally, I also prefer to put the function definition into the patch
which use it.
But the following patch "KVM: Replace old tlb flush function with new
one to flush a specified range"
and other patches which use new functions will change a lot of places.
It's not friendly for review and
so I split them into pieces.
--
Best regards
Tianyu Lan
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH V3 2/13] KVM/MMU: Add tlb flush with range helper function

2018-10-08 Thread Tianyu Lan
Hi Paolo:
  Thanks for your review. Sorry for later response due to holiday.

On Mon, Oct 1, 2018 at 11:26 PM Paolo Bonzini  wrote:
>
> On 27/09/2018 05:48, Tianyu Lan wrote:
> > +
> > + if (range && kvm_x86_ops->tlb_remote_flush_with_range) {
> > + /*
> > +  * Read tlbs_dirty before flushing tlbs in order
> > +  * to track dirty tlbs during flushing.
> > +  */
> > + long dirty_count = smp_load_acquire(>tlbs_dirty);
> > +
> > + ret = kvm_x86_ops->tlb_remote_flush_with_range(kvm, range);
> > + cmpxchg(>tlbs_dirty, dirty_count, 0);
>
> This is wrong, because it's not the entire TLB that is flushed.  So you
> cannot do the cmpxchg here.

Yes, nice catch. Will update in the next version.


-- 
Best regards
Tianyu Lan
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH V3 10/13] x86/hyper-v: Add HvFlushGuestAddressList hypercall support

2018-09-26 Thread Tianyu Lan
On 9/27/2018 12:16 PM, Michael Kelley (EOSG) wrote:
> From: Tianyu Lan  Sent: Wednesday, September 26, 2018 8:50 PM
>>
>> Hyper-V provides HvFlushGuestAddressList() hypercall to flush EPT tlb
>> with specified ranges. This patch is to add the hypercall support.
>>
>> Signed-off-by: Lan Tianyu 
>>
> 
> Looks good!
> 
> Reviewed-by:  Michael Kelley 
> 

Thanks.
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH V3 7/13] KVM: Add flush_link and parent_pte in the struct kvm_mmu_page

2018-09-26 Thread Tianyu Lan
PV EPT tlb flush function will accept a list of flush ranges and
use struct kvm_mmu_page as the list entry.

Signed-off-by: Lan Tianyu 
---
 arch/x86/include/asm/kvm_host.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index a6b77978502e..c96bc4cbe4b7 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -279,6 +279,7 @@ struct kvm_rmap_head {
 
 struct kvm_mmu_page {
struct list_head link;
+   struct list_head flush_link;
struct hlist_node hash_link;
 
/*
-- 
2.14.4
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH V3 10/13] x86/hyper-v: Add HvFlushGuestAddressList hypercall support

2018-09-26 Thread Tianyu Lan
Hyper-V provides HvFlushGuestAddressList() hypercall to flush EPT tlb
with specified ranges. This patch is to add the hypercall support.

Signed-off-by: Lan Tianyu 
---
Change since v2:
  Fix some coding style issues
- Move HV_MAX_FLUSH_PAGES and HV_MAX_FLUSH_REP_COUNT to
hyperv-tlfs.h.
- Calculate HV_MAX_FLUSH_REP_COUNT in the macro definition
- Use HV_MAX_FLUSH_REP_COUNT to define length of gpa_list in
struct hv_guest_mapping_flush_list.

Change since v1:
   Add hyperv tlb flush struct to avoid use kvm tlb flush struct
in the hyperv file.
---
 arch/x86/hyperv/nested.c   | 84 ++
 arch/x86/include/asm/hyperv-tlfs.h | 32 +++
 arch/x86/include/asm/mshyperv.h| 16 
 3 files changed, 132 insertions(+)

diff --git a/arch/x86/hyperv/nested.c b/arch/x86/hyperv/nested.c
index b8e60cc50461..a6fdfec63c7d 100644
--- a/arch/x86/hyperv/nested.c
+++ b/arch/x86/hyperv/nested.c
@@ -7,6 +7,7 @@
  *
  * Author : Lan Tianyu 
  */
+#define pr_fmt(fmt)  "Hyper-V: " fmt
 
 
 #include 
@@ -54,3 +55,86 @@ int hyperv_flush_guest_mapping(u64 as)
return ret;
 }
 EXPORT_SYMBOL_GPL(hyperv_flush_guest_mapping);
+
+static int fill_flush_list(union hv_gpa_page_range gpa_list[],
+   int offset, u64 start_gfn, u64 pages)
+{
+   int gpa_n = offset;
+   u64 cur = start_gfn;
+   u64 additional_pages;
+
+   do {
+   /*
+* If flush requests exceed max flush count, go back to
+* flush tlbs without range.
+*/
+   if (gpa_n >= HV_MAX_FLUSH_REP_COUNT)
+   return -ENOSPC;
+
+   additional_pages = min_t(u64, pages, HV_MAX_FLUSH_PAGES) - 1;
+
+   gpa_list[gpa_n].page.additional_pages = additional_pages;
+   gpa_list[gpa_n].page.largepage = false;
+   gpa_list[gpa_n].page.basepfn = cur;
+
+   pages -= additional_pages + 1;
+   cur += additional_pages + 1;
+   gpa_n++;
+   } while (pages > 0);
+
+   return gpa_n;
+}
+
+int hyperv_flush_guest_mapping_range(u64 as, struct hyperv_tlb_range *range)
+{
+   struct hv_guest_mapping_flush_list **flush_pcpu;
+   struct hv_guest_mapping_flush_list *flush;
+   u64 status = 0;
+   unsigned long flags;
+   int ret = -ENOTSUPP;
+   int gpa_n = 0;
+
+   if (!hv_hypercall_pg)
+   goto fault;
+
+   local_irq_save(flags);
+
+   flush_pcpu = (struct hv_guest_mapping_flush_list **)
+   this_cpu_ptr(hyperv_pcpu_input_arg);
+
+   flush = *flush_pcpu;
+   if (unlikely(!flush)) {
+   local_irq_restore(flags);
+   goto fault;
+   }
+
+   flush->address_space = as;
+   flush->flags = 0;
+
+   if (!range->flush_list)
+   gpa_n = fill_flush_list(flush->gpa_list, gpa_n,
+   range->start_gfn, range->pages);
+   else if (range->parse_flush_list_func)
+   gpa_n = range->parse_flush_list_func(flush->gpa_list, gpa_n,
+   range->flush_list, fill_flush_list);
+   else
+   gpa_n = -1;
+
+   if (gpa_n < 0) {
+   local_irq_restore(flags);
+   goto fault;
+   }
+
+   status = hv_do_rep_hypercall(HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_LIST,
+gpa_n, 0, flush, NULL);
+
+   local_irq_restore(flags);
+
+   if (!(status & HV_HYPERCALL_RESULT_MASK))
+   ret = 0;
+   else
+   ret = status;
+fault:
+   return ret;
+}
+EXPORT_SYMBOL_GPL(hyperv_flush_guest_mapping_range);
diff --git a/arch/x86/include/asm/hyperv-tlfs.h 
b/arch/x86/include/asm/hyperv-tlfs.h
index e977b6b3a538..e38743328dfc 100644
--- a/arch/x86/include/asm/hyperv-tlfs.h
+++ b/arch/x86/include/asm/hyperv-tlfs.h
@@ -10,6 +10,7 @@
 #define _ASM_X86_HYPERV_TLFS_H
 
 #include 
+#include 
 
 /*
  * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent
@@ -353,6 +354,7 @@ struct hv_tsc_emulation_status {
 #define HVCALL_POST_MESSAGE0x005c
 #define HVCALL_SIGNAL_EVENT0x005d
 #define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE 0x00af
+#define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_LIST 0x00b0
 
 #define HV_X64_MSR_VP_ASSIST_PAGE_ENABLE   0x0001
 #define HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_SHIFT12
@@ -750,6 +752,36 @@ struct hv_guest_mapping_flush {
u64 flags;
 };
 
+/*
+ *  HV_MAX_FLUSH_PAGES = "additional_pages" + 1. It's limited
+ *  by the bitwidth of "additional_pages" in union hv_gpa_page_range.
+ */
+#define HV_MAX_FLUSH_PAGES (2048)
+
+/* HvFlushGuestPhysicalAddressList hypercall */
+union hv_gpa_page_range {
+   u64 address_space;
+   struct {
+   u64 additional_pages:11;
+   u64 largepage:1;
+   u64 basepfn:52;
+   } page;

[PATCH V3 9/13] KVM/MMU: Replace tlb flush function with range list flush function

2018-09-26 Thread Tianyu Lan
This patch is to use range list flush function in the
mmu_sync_children(), kvm_mmu_commit_zap_page() and
FNAME(sync_page)().

Signed-off-by: Lan Tianyu 
---
 arch/x86/kvm/mmu.c | 26 +++---
 arch/x86/kvm/paging_tmpl.h |  5 -
 2 files changed, 27 insertions(+), 4 deletions(-)

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index a1cbbc852271..5f3a69425142 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -1092,6 +1092,13 @@ static void update_gfn_disallow_lpage_count(struct 
kvm_memory_slot *slot,
}
 }
 
+static void kvm_mmu_queue_flush_request(struct kvm_mmu_page *sp,
+   struct list_head *flush_list)
+{
+   if (sp->sptep && is_last_spte(*sp->sptep, sp->role.level))
+   list_add(>flush_link, flush_list);
+}
+
 void kvm_mmu_gfn_disallow_lpage(struct kvm_memory_slot *slot, gfn_t gfn)
 {
update_gfn_disallow_lpage_count(slot, gfn, 1);
@@ -2369,12 +2376,16 @@ static void mmu_sync_children(struct kvm_vcpu *vcpu,
 
while (mmu_unsync_walk(parent, )) {
bool protected = false;
+   LIST_HEAD(flush_list);
 
-   for_each_sp(pages, sp, parents, i)
+   for_each_sp(pages, sp, parents, i) {
protected |= rmap_write_protect(vcpu, sp->gfn);
+   kvm_mmu_queue_flush_request(sp, _list);
+   }
 
if (protected) {
-   kvm_flush_remote_tlbs(vcpu->kvm);
+   kvm_flush_remote_tlbs_with_list(vcpu->kvm,
+   _list);
flush = false;
}
 
@@ -2710,6 +2721,7 @@ static void kvm_mmu_commit_zap_page(struct kvm *kvm,
struct list_head *invalid_list)
 {
struct kvm_mmu_page *sp, *nsp;
+   LIST_HEAD(flush_list);
 
if (list_empty(invalid_list))
return;
@@ -2723,7 +2735,15 @@ static void kvm_mmu_commit_zap_page(struct kvm *kvm,
 * In addition, kvm_flush_remote_tlbs waits for all vcpus to exit
 * guest mode and/or lockless shadow page table walks.
 */
-   kvm_flush_remote_tlbs(kvm);
+   if (kvm_available_flush_tlb_with_range()) {
+   list_for_each_entry(sp, invalid_list, link)
+   kvm_mmu_queue_flush_request(sp, _list);
+
+   if (!list_empty(_list))
+   kvm_flush_remote_tlbs_with_list(kvm, _list);
+   } else {
+   kvm_flush_remote_tlbs(kvm);
+   }
 
list_for_each_entry_safe(sp, nsp, invalid_list, link) {
WARN_ON(!sp->role.invalid || sp->root_count);
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index 5cbaf7c4a729..a5f967e81429 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -972,6 +972,7 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct 
kvm_mmu_page *sp)
bool host_writable;
gpa_t first_pte_gpa;
int set_spte_ret = 0;
+   LIST_HEAD(flush_list);
 
/* direct kvm_mmu_page can not be unsync. */
BUG_ON(sp->role.direct);
@@ -1032,10 +1033,12 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, 
struct kvm_mmu_page *sp)
 pte_access, PT_PAGE_TABLE_LEVEL,
 gfn, spte_to_pfn(sp->spt[i]),
 true, false, host_writable);
+   if (set_spte_ret && kvm_available_flush_tlb_with_range())
+   kvm_mmu_queue_flush_request(sp, _list);
}
 
if (set_spte_ret & SET_SPTE_NEED_REMOTE_TLB_FLUSH)
-   kvm_flush_remote_tlbs(vcpu->kvm);
+   kvm_flush_remote_tlbs_with_list(vcpu->kvm, _list);
 
return nr_present;
 }
-- 
2.14.4
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH V3 3/13] KVM: Replace old tlb flush function with new one to flush a specified range.

2018-09-26 Thread Tianyu Lan
This patch is to replace kvm_flush_remote_tlbs() with kvm_flush_
remote_tlbs_with_address() in some functions without logic change.

Signed-off-by: Lan Tianyu 
---
 arch/x86/kvm/mmu.c | 33 ++---
 arch/x86/kvm/paging_tmpl.h |  3 ++-
 2 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 18cac661a41a..d10d8423e8d6 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -1482,8 +1482,12 @@ static bool __drop_large_spte(struct kvm *kvm, u64 
*sptep)
 
 static void drop_large_spte(struct kvm_vcpu *vcpu, u64 *sptep)
 {
-   if (__drop_large_spte(vcpu->kvm, sptep))
-   kvm_flush_remote_tlbs(vcpu->kvm);
+   if (__drop_large_spte(vcpu->kvm, sptep)) {
+   struct kvm_mmu_page *sp = page_header(__pa(sptep));
+
+   kvm_flush_remote_tlbs_with_address(vcpu->kvm, sp->gfn,
+   KVM_PAGES_PER_HPAGE(sp->role.level));
+   }
 }
 
 /*
@@ -1770,7 +1774,7 @@ static int kvm_set_pte_rmapp(struct kvm *kvm, struct 
kvm_rmap_head *rmap_head,
}
 
if (need_flush)
-   kvm_flush_remote_tlbs(kvm);
+   kvm_flush_remote_tlbs_with_address(kvm, gfn, 1);
 
return 0;
 }
@@ -1951,7 +1955,8 @@ static void rmap_recycle(struct kvm_vcpu *vcpu, u64 
*spte, gfn_t gfn)
rmap_head = gfn_to_rmap(vcpu->kvm, gfn, sp);
 
kvm_unmap_rmapp(vcpu->kvm, rmap_head, NULL, gfn, sp->role.level, 0);
-   kvm_flush_remote_tlbs(vcpu->kvm);
+   kvm_flush_remote_tlbs_with_address(vcpu->kvm, sp->gfn,
+   KVM_PAGES_PER_HPAGE(sp->role.level));
 }
 
 int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end)
@@ -2467,7 +2472,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct 
kvm_vcpu *vcpu,
account_shadowed(vcpu->kvm, sp);
if (level == PT_PAGE_TABLE_LEVEL &&
  rmap_write_protect(vcpu, gfn))
-   kvm_flush_remote_tlbs(vcpu->kvm);
+   kvm_flush_remote_tlbs_with_address(vcpu->kvm, gfn, 1);
 
if (level > PT_PAGE_TABLE_LEVEL && need_sync)
flush |= kvm_sync_pages(vcpu, gfn, _list);
@@ -2587,7 +2592,7 @@ static void validate_direct_spte(struct kvm_vcpu *vcpu, 
u64 *sptep,
return;
 
drop_parent_pte(child, sptep);
-   kvm_flush_remote_tlbs(vcpu->kvm);
+   kvm_flush_remote_tlbs_with_address(vcpu->kvm, child->gfn, 1);
}
 }
 
@@ -3011,8 +3016,10 @@ static int mmu_set_spte(struct kvm_vcpu *vcpu, u64 
*sptep, unsigned pte_access,
ret = RET_PF_EMULATE;
kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
}
+
if (set_spte_ret & SET_SPTE_NEED_REMOTE_TLB_FLUSH || flush)
-   kvm_flush_remote_tlbs(vcpu->kvm);
+   kvm_flush_remote_tlbs_with_address(vcpu->kvm, gfn,
+   KVM_PAGES_PER_HPAGE(level));
 
if (unlikely(is_mmio_spte(*sptep)))
ret = RET_PF_EMULATE;
@@ -5621,7 +5628,8 @@ void kvm_mmu_slot_remove_write_access(struct kvm *kvm,
 * on PT_WRITABLE_MASK anymore.
 */
if (flush)
-   kvm_flush_remote_tlbs(kvm);
+   kvm_flush_remote_tlbs_with_address(kvm, memslot->base_gfn,
+   memslot->npages);
 }
 
 static bool kvm_mmu_zap_collapsible_spte(struct kvm *kvm,
@@ -5685,7 +5693,8 @@ void kvm_mmu_slot_leaf_clear_dirty(struct kvm *kvm,
 * dirty_bitmap.
 */
if (flush)
-   kvm_flush_remote_tlbs(kvm);
+   kvm_flush_remote_tlbs_with_address(kvm, memslot->base_gfn,
+   memslot->npages);
 }
 EXPORT_SYMBOL_GPL(kvm_mmu_slot_leaf_clear_dirty);
 
@@ -5703,7 +5712,8 @@ void kvm_mmu_slot_largepage_remove_write_access(struct 
kvm *kvm,
lockdep_assert_held(>slots_lock);
 
if (flush)
-   kvm_flush_remote_tlbs(kvm);
+   kvm_flush_remote_tlbs_with_address(kvm, memslot->base_gfn,
+   memslot->npages);
 }
 EXPORT_SYMBOL_GPL(kvm_mmu_slot_largepage_remove_write_access);
 
@@ -5720,7 +5730,8 @@ void kvm_mmu_slot_set_dirty(struct kvm *kvm,
 
/* see kvm_mmu_slot_leaf_clear_dirty */
if (flush)
-   kvm_flush_remote_tlbs(kvm);
+   kvm_flush_remote_tlbs_with_address(kvm, memslot->base_gfn,
+   memslot->npages);
 }
 EXPORT_SYMBOL_GPL(kvm_mmu_slot_set_dirty);
 
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index 14ffd973df54..708a5e44861a 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -893,7 +893,8 @@ static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva, 
hpa_t root_hpa)
pte_gpa += (sptep - sp->spt) * sizeof(pt_element_t);
 
if (mmu_page_zap_pte(vcpu->kvm, sp, sptep))

[PATCH V3 8/13] KVM: Add spte's point in the struct kvm_mmu_page

2018-09-26 Thread Tianyu Lan
It's necessary to check whether mmu page is last or large page when add
mmu page into flush list. "spte" is needed for such check and so add
spte point in the struct kvm_mmu_page.

Signed-off-by: Lan Tianyu 
---
 arch/x86/include/asm/kvm_host.h | 1 +
 arch/x86/kvm/mmu.c  | 5 +
 arch/x86/kvm/paging_tmpl.h  | 2 ++
 3 files changed, 8 insertions(+)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index c96bc4cbe4b7..d42d96e637b5 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -296,6 +296,7 @@ struct kvm_mmu_page {
int root_count;  /* Currently serving as active root */
unsigned int unsync_children;
struct kvm_rmap_head parent_ptes; /* rmap pointers to parent sptes */
+   u64 *sptep;
 
/* The page is obsolete if mmu_valid_gen != kvm->arch.mmu_valid_gen.  */
unsigned long mmu_valid_gen;
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 7c508c4bd204..a1cbbc852271 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -3162,6 +3162,7 @@ static int __direct_map(struct kvm_vcpu *vcpu, int write, 
int map_writable,
pseudo_gfn = base_addr >> PAGE_SHIFT;
sp = kvm_mmu_get_page(vcpu, pseudo_gfn, iterator.addr,
  iterator.level - 1, 1, ACC_ALL);
+   sp->sptep = iterator.sptep;
 
link_shadow_page(vcpu, iterator.sptep, sp);
}
@@ -3599,6 +3600,7 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu)
sp = kvm_mmu_get_page(vcpu, 0, 0,
vcpu->arch.mmu.shadow_root_level, 1, ACC_ALL);
++sp->root_count;
+   sp->sptep = NULL;
spin_unlock(>kvm->mmu_lock);
vcpu->arch.mmu.root_hpa = __pa(sp->spt);
} else if (vcpu->arch.mmu.shadow_root_level == PT32E_ROOT_LEVEL) {
@@ -3615,6 +3617,7 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu)
i << 30, PT32_ROOT_LEVEL, 1, ACC_ALL);
root = __pa(sp->spt);
++sp->root_count;
+   sp->sptep = NULL;
spin_unlock(>kvm->mmu_lock);
vcpu->arch.mmu.pae_root[i] = root | PT_PRESENT_MASK;
}
@@ -3655,6 +3658,7 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu)
vcpu->arch.mmu.shadow_root_level, 0, ACC_ALL);
root = __pa(sp->spt);
++sp->root_count;
+   sp->sptep = NULL;
spin_unlock(>kvm->mmu_lock);
vcpu->arch.mmu.root_hpa = root;
return 0;
@@ -3692,6 +3696,7 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu)
  0, ACC_ALL);
root = __pa(sp->spt);
++sp->root_count;
+   sp->sptep = NULL;
spin_unlock(>kvm->mmu_lock);
 
vcpu->arch.mmu.pae_root[i] = root | pm_mask;
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index 708a5e44861a..5cbaf7c4a729 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -632,6 +632,7 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
table_gfn = gw->table_gfn[it.level - 2];
sp = kvm_mmu_get_page(vcpu, table_gfn, addr, it.level-1,
  false, access);
+   sp->sptep = it.sptep;
}
 
/*
@@ -662,6 +663,7 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
 
sp = kvm_mmu_get_page(vcpu, direct_gfn, addr, it.level-1,
  true, direct_access);
+   sp->sptep = it.sptep;
link_shadow_page(vcpu, it.sptep, sp);
}
 
-- 
2.14.4
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH V3 11/13] x86/Hyper-v: Add trace in the hyperv_nested_flush_guest_mapping_range()

2018-09-26 Thread Tianyu Lan
This patch is to trace log in the hyperv_nested_flush_
guest_mapping_range().

Signed-off-by: Lan Tianyu 
---
 arch/x86/hyperv/nested.c|  1 +
 arch/x86/include/asm/trace/hyperv.h | 14 ++
 2 files changed, 15 insertions(+)

diff --git a/arch/x86/hyperv/nested.c b/arch/x86/hyperv/nested.c
index a6fdfec63c7d..4850c74508f3 100644
--- a/arch/x86/hyperv/nested.c
+++ b/arch/x86/hyperv/nested.c
@@ -135,6 +135,7 @@ int hyperv_flush_guest_mapping_range(u64 as, struct 
hyperv_tlb_range *range)
else
ret = status;
 fault:
+   trace_hyperv_nested_flush_guest_mapping_range(as, ret);
return ret;
 }
 EXPORT_SYMBOL_GPL(hyperv_flush_guest_mapping_range);
diff --git a/arch/x86/include/asm/trace/hyperv.h 
b/arch/x86/include/asm/trace/hyperv.h
index 2e6245a023ef..ace464f09681 100644
--- a/arch/x86/include/asm/trace/hyperv.h
+++ b/arch/x86/include/asm/trace/hyperv.h
@@ -42,6 +42,20 @@ TRACE_EVENT(hyperv_nested_flush_guest_mapping,
TP_printk("address space %llx ret %d", __entry->as, __entry->ret)
);
 
+TRACE_EVENT(hyperv_nested_flush_guest_mapping_range,
+   TP_PROTO(u64 as, int ret),
+   TP_ARGS(as, ret),
+
+   TP_STRUCT__entry(
+   __field(u64, as)
+   __field(int, ret)
+   ),
+   TP_fast_assign(__entry->as = as;
+  __entry->ret = ret;
+   ),
+   TP_printk("address space %llx ret %d", __entry->as, __entry->ret)
+   );
+
 TRACE_EVENT(hyperv_send_ipi_mask,
TP_PROTO(const struct cpumask *cpus,
 int vector),
-- 
2.14.4
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH V3 4/13] KVM/MMU: Flush tlb directly in the kvm_handle_hva_range()

2018-09-26 Thread Tianyu Lan
This patch is to flush tlb directly in the kvm_handle_hva_range()
when range flush is available.

Signed-off-by: Lan Tianyu 
---
 arch/x86/kvm/mmu.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index d10d8423e8d6..877edae0401f 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -1888,6 +1888,13 @@ static int kvm_handle_hva_range(struct kvm *kvm,
 )
ret |= handler(kvm, iterator.rmap, memslot,
   iterator.gfn, iterator.level, 
data);
+
+   if (ret && kvm_available_flush_tlb_with_range()) {
+   kvm_flush_remote_tlbs_with_address(kvm,
+   gfn_start,
+   gfn_end - gfn_start);
+   ret = 0;
+   }
}
}
 
-- 
2.14.4
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH V3 1/13] KVM: Add tlb_remote_flush_with_range callback in kvm_x86_ops

2018-09-26 Thread Tianyu Lan
Add flush range call back in the kvm_x86_ops and platform can use it
to register its associated function. The parameter "kvm_tlb_range"
accepts a single range and flush list which contains a list of ranges.

Signed-off-by: Lan Tianyu 
---
Change since v1:
   Change "end_gfn" to "pages" to aviod confusion as to whether
"end_gfn" is inclusive or exlusive.
---
 arch/x86/include/asm/kvm_host.h | 8 
 1 file changed, 8 insertions(+)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 8e90488c3d56..a6b77978502e 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -402,6 +402,12 @@ struct kvm_mmu {
u64 pdptrs[4]; /* pae */
 };
 
+struct kvm_tlb_range {
+   u64 start_gfn;
+   u64 pages;
+   struct list_head *flush_list;
+};
+
 enum pmc_type {
KVM_PMC_GP = 0,
KVM_PMC_FIXED,
@@ -991,6 +997,8 @@ struct kvm_x86_ops {
 
void (*tlb_flush)(struct kvm_vcpu *vcpu, bool invalidate_gpa);
int  (*tlb_remote_flush)(struct kvm *kvm);
+   int  (*tlb_remote_flush_with_range)(struct kvm *kvm,
+   struct kvm_tlb_range *range);
 
/*
 * Flush any TLB entries associated with the given GVA.
-- 
2.14.4
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH V3 5/13] KVM/MMU: Flush tlb directly in the kvm_zap_gfn_range()

2018-09-26 Thread Tianyu Lan
Originally, flush tlb is done by slot_handle_level_range(). This patch
is to flush tlb directly in the kvm_zap_gfn_range() when range
flush is available.

Signed-off-by: Lan Tianyu 
---
 arch/x86/kvm/mmu.c | 16 +---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 877edae0401f..f24101ef763e 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -5578,6 +5578,7 @@ void kvm_zap_gfn_range(struct kvm *kvm, gfn_t gfn_start, 
gfn_t gfn_end)
 {
struct kvm_memslots *slots;
struct kvm_memory_slot *memslot;
+   bool flush = false;
int i;
 
spin_lock(>mmu_lock);
@@ -5585,18 +5586,27 @@ void kvm_zap_gfn_range(struct kvm *kvm, gfn_t 
gfn_start, gfn_t gfn_end)
slots = __kvm_memslots(kvm, i);
kvm_for_each_memslot(memslot, slots) {
gfn_t start, end;
+   bool flush_tlb = true;
 
start = max(gfn_start, memslot->base_gfn);
end = min(gfn_end, memslot->base_gfn + memslot->npages);
if (start >= end)
continue;
 
-   slot_handle_level_range(kvm, memslot, kvm_zap_rmapp,
-   PT_PAGE_TABLE_LEVEL, 
PT_MAX_HUGEPAGE_LEVEL,
-   start, end - 1, true);
+   if (kvm_available_flush_tlb_with_range())
+   flush_tlb = false;
+
+   flush = slot_handle_level_range(kvm, memslot,
+   kvm_zap_rmapp, PT_PAGE_TABLE_LEVEL,
+   PT_MAX_HUGEPAGE_LEVEL, start,
+   end - 1, flush_tlb);
}
}
 
+   if (flush && kvm_available_flush_tlb_with_range())
+   kvm_flush_remote_tlbs_with_address(kvm, gfn_start,
+   gfn_end - gfn_start + 1);
+
spin_unlock(>mmu_lock);
 }
 
-- 
2.14.4
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH V3 2/13] KVM/MMU: Add tlb flush with range helper function

2018-09-26 Thread Tianyu Lan
This patch is to add wrapper functions for tlb_remote_flush_with_range
callback.

Signed-off-by: Lan Tianyu 
---
Change since V2:
   Fix comment in the kvm_flush_remote_tlbs_with_range()
---
 arch/x86/kvm/mmu.c | 48 
 1 file changed, 48 insertions(+)

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index c67f09086378..18cac661a41a 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -253,6 +253,54 @@ static void mmu_spte_set(u64 *sptep, u64 spte);
 static union kvm_mmu_page_role
 kvm_mmu_calc_root_page_role(struct kvm_vcpu *vcpu);
 
+
+static inline bool kvm_available_flush_tlb_with_range(void)
+{
+   return kvm_x86_ops->tlb_remote_flush_with_range;
+}
+
+static void kvm_flush_remote_tlbs_with_range(struct kvm *kvm,
+   struct kvm_tlb_range *range)
+{
+   int ret = -ENOTSUPP;
+
+   if (range && kvm_x86_ops->tlb_remote_flush_with_range) {
+   /*
+* Read tlbs_dirty before flushing tlbs in order
+* to track dirty tlbs during flushing.
+*/
+   long dirty_count = smp_load_acquire(>tlbs_dirty);
+
+   ret = kvm_x86_ops->tlb_remote_flush_with_range(kvm, range);
+   cmpxchg(>tlbs_dirty, dirty_count, 0);
+   }
+
+   if (ret)
+   kvm_flush_remote_tlbs(kvm);
+}
+
+static void kvm_flush_remote_tlbs_with_list(struct kvm *kvm,
+   struct list_head *flush_list)
+{
+   struct kvm_tlb_range range;
+
+   range.flush_list = flush_list;
+
+   kvm_flush_remote_tlbs_with_range(kvm, );
+}
+
+static void kvm_flush_remote_tlbs_with_address(struct kvm *kvm,
+   u64 start_gfn, u64 pages)
+{
+   struct kvm_tlb_range range;
+
+   range.start_gfn = start_gfn;
+   range.pages = pages;
+   range.flush_list = NULL;
+
+   kvm_flush_remote_tlbs_with_range(kvm, );
+}
+
 void kvm_mmu_set_mmio_spte_mask(u64 mmio_mask, u64 mmio_value)
 {
BUG_ON((mmio_mask & mmio_value) != mmio_value);
-- 
2.14.4
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH V3 00/13] x86/KVM/Hyper-v: Add HV ept tlb range flush hypercall support in KVM

2018-09-26 Thread Tianyu Lan
For nested memory virtualization, Hyper-v doesn't set write-protect
L1 hypervisor EPT page directory and page table node to track changes 
while it relies on guest to tell it changes via HvFlushGuestAddressLlist
hypercall. HvFlushGuestAddressLlist hypercall provides a way to flush
EPT page table with ranges which are specified by L1 hypervisor.

If L1 hypervisor uses INVEPT or HvFlushGuestAddressSpace hypercall to
flush EPT tlb, Hyper-V will invalidate associated EPT shadow page table
and sync L1's EPT table when next EPT page fault is triggered.
HvFlushGuestAddressLlist hypercall helps to avoid such redundant EPT
page fault and synchronization of shadow page table.

Change since v2:
   1) Fix comment in the kvm_flush_remote_tlbs_with_range()
   2) Move HV_MAX_FLUSH_PAGES and HV_MAX_FLUSH_REP_COUNT to
hyperv-tlfs.h.
   3) Calculate HV_MAX_FLUSH_REP_COUNT in the macro definition
   4) Use HV_MAX_FLUSH_REP_COUNT to define length of gpa_list in
struct hv_guest_mapping_flush_list.


Change since v1:
   1) Convert "end_gfn" of struct kvm_tlb_range to "pages" in order
  to avoid confusion as to whether "end_gfn" is inclusive or exlusive.
   2) Add hyperv tlb range struct and replace kvm tlb range struct
  with new struct in order to avoid using kvm struct in the hyperv
  code directly.


Lan Tianyu (13):
  KVM: Add tlb_remote_flush_with_range callback in kvm_x86_ops
  KVM/MMU: Add tlb flush with range helper function
  KVM: Replace old tlb flush function with new one to flush a specified
range.
  KVM/MMU: Flush tlb directly in the kvm_handle_hva_range()
  KVM/MMU: Flush tlb directly in the kvm_zap_gfn_range()
  KVM/MMU: Flush tlb directly in kvm_mmu_zap_collapsible_spte()
  KVM: Add flush_link and parent_pte in the struct kvm_mmu_page
  KVM: Add spte's point in the struct kvm_mmu_page
  KVM/MMU: Replace tlb flush function with range list flush function
  x86/hyper-v: Add HvFlushGuestAddressList hypercall support
  x86/Hyper-v: Add trace in the
hyperv_nested_flush_guest_mapping_range()
  KVM/VMX: Change hv flush logic when ept tables are mismatched.
  KVM/VMX: Add hv tlb range flush support

 arch/x86/hyperv/nested.c|  85 +
 arch/x86/include/asm/hyperv-tlfs.h  |  32 
 arch/x86/include/asm/kvm_host.h |  10 +++
 arch/x86/include/asm/mshyperv.h |  16 
 arch/x86/include/asm/trace/hyperv.h |  14 
 arch/x86/kvm/mmu.c  | 143 +++-
 arch/x86/kvm/paging_tmpl.h  |  10 ++-
 arch/x86/kvm/vmx.c  |  65 +---
 8 files changed, 345 insertions(+), 30 deletions(-)

-- 
2.14.4
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH V3 6/13] KVM/MMU: Flush tlb directly in kvm_mmu_zap_collapsible_spte()

2018-09-26 Thread Tianyu Lan
kvm_mmu_zap_collapsible_spte() returns flush request to the
slot_handle_leaf() and the latter does flush on demand. When
range flush is available, make kvm_mmu_zap_collapsible_spte()
to flush tlb with range directly to avoid returning range back
to slot_handle_leaf().

Signed-off-by: Lan Tianyu 
---
 arch/x86/kvm/mmu.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index f24101ef763e..7c508c4bd204 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -5674,7 +5674,13 @@ static bool kvm_mmu_zap_collapsible_spte(struct kvm *kvm,
!kvm_is_reserved_pfn(pfn) &&
PageTransCompoundMap(pfn_to_page(pfn))) {
drop_spte(kvm, sptep);
-   need_tlb_flush = 1;
+
+   if (kvm_available_flush_tlb_with_range())
+   kvm_flush_remote_tlbs_with_address(kvm, sp->gfn,
+   KVM_PAGES_PER_HPAGE(sp->role.level));
+   else
+   need_tlb_flush = 1;
+
goto restart;
}
}
-- 
2.14.4
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH V2 4/13] KVM/MMU: Flush tlb directly in the kvm_handle_hva_range()

2018-09-20 Thread Tianyu Lan
On 9/20/2018 12:08 AM, Michael Kelley (EOSG) wrote:
> From: Tianyu Lan  Sent: Monday, September 17, 2018 8:19 PM
>> +
>> +if (ret && kvm_available_flush_tlb_with_range()) {
>> +kvm_flush_remote_tlbs_with_address(kvm,
>> +gfn_start,
>> +gfn_end - gfn_start);
> 
> Does the above need to be gfn_end - gfn_start + 1?

The flush range depends on the input parameter frame start and frame end 
of for_each_slot_rmap_range().

 for_each_slot_rmap_range(memslot, PT_PAGE_TABLE_LEVEL,
  PT_MAX_HUGEPAGE_LEVEL,
  gfn_start, gfn_end - 1,
  )
 ret |= handler(kvm, iterator.rmap, memslot,
iterator.gfn, iterator.level, data);


The start is "gfn_start" and the end is "gfn_end - 1". The flush size is 
(gfn_end - 1) - gfn_start + 1 = gfn_end - gfn_start.

> 
>> +ret = 0;
>> +}
> 
> Michael
> 
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH V2 10/13] x86/hyper-v: Add HvFlushGuestAddressList hypercall support

2018-09-17 Thread Tianyu Lan
Hyper-V provides HvFlushGuestAddressList() hypercall to flush EPT tlb
with specified ranges. This patch is to add the hypercall support.

Signed-off-by: Lan Tianyu 
---
Change since v1:
   Add hyperv tlb flush struct to avoid use kvm tlb flush struct
in the hyperv file.
---
 arch/x86/hyperv/nested.c   | 103 +
 arch/x86/include/asm/hyperv-tlfs.h |  17 ++
 arch/x86/include/asm/mshyperv.h|  16 ++
 3 files changed, 136 insertions(+)

diff --git a/arch/x86/hyperv/nested.c b/arch/x86/hyperv/nested.c
index b8e60cc50461..40ddbfd54573 100644
--- a/arch/x86/hyperv/nested.c
+++ b/arch/x86/hyperv/nested.c
@@ -7,15 +7,32 @@
  *
  * Author : Lan Tianyu 
  */
+#define pr_fmt(fmt)  "Hyper-V: " fmt
 
 
 #include 
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
+/*
+ *  MAX_FLUSH_PAGES = "additional_pages" + 1. It's limited
+ *  by the bitwidth of "additional_pages" in union hv_gpa_page_range.
+ */
+#define MAX_FLUSH_PAGES (2048)
+
+/*
+ * All input flush parameters are in single page. The max flush count
+ * is equal with how many entries of union hv_gpa_page_range can be
+ * populated in the input parameter page. MAX_FLUSH_REP_COUNT
+ * = (4096 - 16) / 8. (“Page Size” - "Address Space" - "Flags") /
+ * "GPA Range".
+ */
+#define MAX_FLUSH_REP_COUNT (510)
+
 int hyperv_flush_guest_mapping(u64 as)
 {
struct hv_guest_mapping_flush **flush_pcpu;
@@ -54,3 +71,89 @@ int hyperv_flush_guest_mapping(u64 as)
return ret;
 }
 EXPORT_SYMBOL_GPL(hyperv_flush_guest_mapping);
+
+static int fill_flush_list(union hv_gpa_page_range gpa_list[],
+   int offset, u64 start_gfn, u64 pages)
+{
+   int gpa_n = offset;
+   u64 cur = start_gfn;
+   u64 additional_pages;
+
+   do {
+   if (gpa_n >= MAX_FLUSH_REP_COUNT) {
+   pr_warn("Request exceeds HvFlushGuestList max flush 
count.");
+   return -ENOSPC;
+   }
+
+   if (pages > MAX_FLUSH_PAGES) {
+   additional_pages = MAX_FLUSH_PAGES - 1;
+   pages -= MAX_FLUSH_PAGES;
+   } else {
+   additional_pages = pages - 1;
+   pages = 0;
+   }
+
+   gpa_list[gpa_n].page.additional_pages = additional_pages;
+   gpa_list[gpa_n].page.largepage = false;
+   gpa_list[gpa_n].page.basepfn = cur;
+
+   cur += additional_pages + 1;
+   gpa_n++;
+   } while (pages > 0);
+
+   return gpa_n;
+}
+
+int hyperv_flush_guest_mapping_range(u64 as, struct hyperv_tlb_range *range)
+{
+   struct hv_guest_mapping_flush_list **flush_pcpu;
+   struct hv_guest_mapping_flush_list *flush;
+   u64 status = 0;
+   unsigned long flags;
+   int ret = -ENOTSUPP;
+   int gpa_n = 0;
+
+   if (!hv_hypercall_pg)
+   goto fault;
+
+   local_irq_save(flags);
+
+   flush_pcpu = (struct hv_guest_mapping_flush_list **)
+   this_cpu_ptr(hyperv_pcpu_input_arg);
+
+   flush = *flush_pcpu;
+   if (unlikely(!flush)) {
+   local_irq_restore(flags);
+   goto fault;
+   }
+
+   flush->address_space = as;
+   flush->flags = 0;
+
+   if (!range->flush_list)
+   gpa_n = fill_flush_list(flush->gpa_list, gpa_n,
+   range->start_gfn, range->pages);
+   else if (range->parse_flush_list_func)
+   gpa_n = range->parse_flush_list_func(flush->gpa_list, gpa_n,
+   range->flush_list, fill_flush_list);
+   else
+   gpa_n = -1;
+
+   if (gpa_n < 0) {
+   local_irq_restore(flags);
+   goto fault;
+   }
+
+   status = hv_do_rep_hypercall(HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_LIST,
+gpa_n, 0, flush, NULL);
+
+   local_irq_restore(flags);
+
+   if (!(status & HV_HYPERCALL_RESULT_MASK))
+   ret = 0;
+   else
+   ret = status;
+fault:
+   return ret;
+}
+EXPORT_SYMBOL_GPL(hyperv_flush_guest_mapping_range);
diff --git a/arch/x86/include/asm/hyperv-tlfs.h 
b/arch/x86/include/asm/hyperv-tlfs.h
index e977b6b3a538..512f22b4 100644
--- a/arch/x86/include/asm/hyperv-tlfs.h
+++ b/arch/x86/include/asm/hyperv-tlfs.h
@@ -353,6 +353,7 @@ struct hv_tsc_emulation_status {
 #define HVCALL_POST_MESSAGE0x005c
 #define HVCALL_SIGNAL_EVENT0x005d
 #define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE 0x00af
+#define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_LIST 0x00b0
 
 #define HV_X64_MSR_VP_ASSIST_PAGE_ENABLE   0x0001
 #define HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_SHIFT12
@@ -750,6 +751,22 @@ struct hv_guest_mapping_flush {
u64 flags;
 };
 
+/* HvFlushGuestPhysicalAddressList hypercall */
+union hv_gpa_page_range {
+   u64 address_space;
+   struct {
+   

[PATCH V2 6/13] KVM/MMU: Flush tlb directly in kvm_mmu_zap_collapsible_spte()

2018-09-17 Thread Tianyu Lan
kvm_mmu_zap_collapsible_spte() returns flush request to the
slot_handle_leaf() and the latter does flush on demand. When
range flush is available, make kvm_mmu_zap_collapsible_spte()
to flush tlb with range directly to avoid returning range back
to slot_handle_leaf().

Signed-off-by: Lan Tianyu 
---
 arch/x86/kvm/mmu.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 56538fa6c017..85a81a62e0a7 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -5674,7 +5674,13 @@ static bool kvm_mmu_zap_collapsible_spte(struct kvm *kvm,
!kvm_is_reserved_pfn(pfn) &&
PageTransCompoundMap(pfn_to_page(pfn))) {
drop_spte(kvm, sptep);
-   need_tlb_flush = 1;
+
+   if (kvm_available_flush_tlb_with_range())
+   kvm_flush_remote_tlbs_with_address(kvm, sp->gfn,
+   KVM_PAGES_PER_HPAGE(sp->role.level));
+   else
+   need_tlb_flush = 1;
+
goto restart;
}
}
-- 
2.14.4
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH V2 11/13] x86/Hyper-v: Add trace in the hyperv_nested_flush_guest_mapping_range()

2018-09-17 Thread Tianyu Lan
This patch is to trace log in the hyperv_nested_flush_
guest_mapping_range().

Signed-off-by: Lan Tianyu 
---
 arch/x86/hyperv/nested.c|  1 +
 arch/x86/include/asm/trace/hyperv.h | 14 ++
 2 files changed, 15 insertions(+)

diff --git a/arch/x86/hyperv/nested.c b/arch/x86/hyperv/nested.c
index 40ddbfd54573..ae7181c6ede4 100644
--- a/arch/x86/hyperv/nested.c
+++ b/arch/x86/hyperv/nested.c
@@ -154,6 +154,7 @@ int hyperv_flush_guest_mapping_range(u64 as, struct 
hyperv_tlb_range *range)
else
ret = status;
 fault:
+   trace_hyperv_nested_flush_guest_mapping_range(as, ret);
return ret;
 }
 EXPORT_SYMBOL_GPL(hyperv_flush_guest_mapping_range);
diff --git a/arch/x86/include/asm/trace/hyperv.h 
b/arch/x86/include/asm/trace/hyperv.h
index 2e6245a023ef..ace464f09681 100644
--- a/arch/x86/include/asm/trace/hyperv.h
+++ b/arch/x86/include/asm/trace/hyperv.h
@@ -42,6 +42,20 @@ TRACE_EVENT(hyperv_nested_flush_guest_mapping,
TP_printk("address space %llx ret %d", __entry->as, __entry->ret)
);
 
+TRACE_EVENT(hyperv_nested_flush_guest_mapping_range,
+   TP_PROTO(u64 as, int ret),
+   TP_ARGS(as, ret),
+
+   TP_STRUCT__entry(
+   __field(u64, as)
+   __field(int, ret)
+   ),
+   TP_fast_assign(__entry->as = as;
+  __entry->ret = ret;
+   ),
+   TP_printk("address space %llx ret %d", __entry->as, __entry->ret)
+   );
+
 TRACE_EVENT(hyperv_send_ipi_mask,
TP_PROTO(const struct cpumask *cpus,
 int vector),
-- 
2.14.4
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH V2 8/13] KVM: Add spte's point in the struct kvm_mmu_page

2018-09-17 Thread Tianyu Lan
It's necessary to check whether mmu page is last or large page when add
mmu page into flush list. "spte" is needed for such check and so add
spte point in the struct kvm_mmu_page.

Signed-off-by: Lan Tianyu 
---
 arch/x86/include/asm/kvm_host.h | 1 +
 arch/x86/kvm/mmu.c  | 5 +
 arch/x86/kvm/paging_tmpl.h  | 2 ++
 3 files changed, 8 insertions(+)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index c96bc4cbe4b7..d42d96e637b5 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -296,6 +296,7 @@ struct kvm_mmu_page {
int root_count;  /* Currently serving as active root */
unsigned int unsync_children;
struct kvm_rmap_head parent_ptes; /* rmap pointers to parent sptes */
+   u64 *sptep;
 
/* The page is obsolete if mmu_valid_gen != kvm->arch.mmu_valid_gen.  */
unsigned long mmu_valid_gen;
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 85a81a62e0a7..8f27cb8c3989 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -3162,6 +3162,7 @@ static int __direct_map(struct kvm_vcpu *vcpu, int write, 
int map_writable,
pseudo_gfn = base_addr >> PAGE_SHIFT;
sp = kvm_mmu_get_page(vcpu, pseudo_gfn, iterator.addr,
  iterator.level - 1, 1, ACC_ALL);
+   sp->sptep = iterator.sptep;
 
link_shadow_page(vcpu, iterator.sptep, sp);
}
@@ -3599,6 +3600,7 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu)
sp = kvm_mmu_get_page(vcpu, 0, 0,
vcpu->arch.mmu.shadow_root_level, 1, ACC_ALL);
++sp->root_count;
+   sp->sptep = NULL;
spin_unlock(>kvm->mmu_lock);
vcpu->arch.mmu.root_hpa = __pa(sp->spt);
} else if (vcpu->arch.mmu.shadow_root_level == PT32E_ROOT_LEVEL) {
@@ -3615,6 +3617,7 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu)
i << 30, PT32_ROOT_LEVEL, 1, ACC_ALL);
root = __pa(sp->spt);
++sp->root_count;
+   sp->sptep = NULL;
spin_unlock(>kvm->mmu_lock);
vcpu->arch.mmu.pae_root[i] = root | PT_PRESENT_MASK;
}
@@ -3655,6 +3658,7 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu)
vcpu->arch.mmu.shadow_root_level, 0, ACC_ALL);
root = __pa(sp->spt);
++sp->root_count;
+   sp->sptep = NULL;
spin_unlock(>kvm->mmu_lock);
vcpu->arch.mmu.root_hpa = root;
return 0;
@@ -3692,6 +3696,7 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu)
  0, ACC_ALL);
root = __pa(sp->spt);
++sp->root_count;
+   sp->sptep = NULL;
spin_unlock(>kvm->mmu_lock);
 
vcpu->arch.mmu.pae_root[i] = root | pm_mask;
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index 708a5e44861a..5cbaf7c4a729 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -632,6 +632,7 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
table_gfn = gw->table_gfn[it.level - 2];
sp = kvm_mmu_get_page(vcpu, table_gfn, addr, it.level-1,
  false, access);
+   sp->sptep = it.sptep;
}
 
/*
@@ -662,6 +663,7 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
 
sp = kvm_mmu_get_page(vcpu, direct_gfn, addr, it.level-1,
  true, direct_access);
+   sp->sptep = it.sptep;
link_shadow_page(vcpu, it.sptep, sp);
}
 
-- 
2.14.4
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH V2 5/13] KVM/MMU: Flush tlb directly in the kvm_zap_gfn_range()

2018-09-17 Thread Tianyu Lan
Originally, flush tlb is done by slot_handle_level_range(). This patch
is to flush tlb directly in the kvm_zap_gfn_range() when range
flush is available.

Signed-off-by: Lan Tianyu 
---
 arch/x86/kvm/mmu.c | 16 +---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index dfd2a0710417..56538fa6c017 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -5578,6 +5578,7 @@ void kvm_zap_gfn_range(struct kvm *kvm, gfn_t gfn_start, 
gfn_t gfn_end)
 {
struct kvm_memslots *slots;
struct kvm_memory_slot *memslot;
+   bool flush = false;
int i;
 
spin_lock(>mmu_lock);
@@ -5585,18 +5586,27 @@ void kvm_zap_gfn_range(struct kvm *kvm, gfn_t 
gfn_start, gfn_t gfn_end)
slots = __kvm_memslots(kvm, i);
kvm_for_each_memslot(memslot, slots) {
gfn_t start, end;
+   bool flush_tlb = true;
 
start = max(gfn_start, memslot->base_gfn);
end = min(gfn_end, memslot->base_gfn + memslot->npages);
if (start >= end)
continue;
 
-   slot_handle_level_range(kvm, memslot, kvm_zap_rmapp,
-   PT_PAGE_TABLE_LEVEL, 
PT_MAX_HUGEPAGE_LEVEL,
-   start, end - 1, true);
+   if (kvm_available_flush_tlb_with_range())
+   flush_tlb = false;
+
+   flush = slot_handle_level_range(kvm, memslot,
+   kvm_zap_rmapp, PT_PAGE_TABLE_LEVEL,
+   PT_MAX_HUGEPAGE_LEVEL, start,
+   end - 1, flush_tlb);
}
}
 
+   if (flush && kvm_available_flush_tlb_with_range())
+   kvm_flush_remote_tlbs_with_address(kvm, gfn_start,
+   gfn_end - gfn_start + 1);
+
spin_unlock(>mmu_lock);
 }
 
-- 
2.14.4
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH V2 9/13] KVM/MMU: Replace tlb flush function with range list flush function

2018-09-17 Thread Tianyu Lan
This patch is to use range list flush function in the
mmu_sync_children(), kvm_mmu_commit_zap_page() and
FNAME(sync_page)().

Signed-off-by: Lan Tianyu 
---
 arch/x86/kvm/mmu.c | 26 +++---
 arch/x86/kvm/paging_tmpl.h |  5 -
 2 files changed, 27 insertions(+), 4 deletions(-)

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 8f27cb8c3989..0390e67715ee 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -1092,6 +1092,13 @@ static void update_gfn_disallow_lpage_count(struct 
kvm_memory_slot *slot,
}
 }
 
+static void kvm_mmu_queue_flush_request(struct kvm_mmu_page *sp,
+   struct list_head *flush_list)
+{
+   if (sp->sptep && is_last_spte(*sp->sptep, sp->role.level))
+   list_add(>flush_link, flush_list);
+}
+
 void kvm_mmu_gfn_disallow_lpage(struct kvm_memory_slot *slot, gfn_t gfn)
 {
update_gfn_disallow_lpage_count(slot, gfn, 1);
@@ -2369,12 +2376,16 @@ static void mmu_sync_children(struct kvm_vcpu *vcpu,
 
while (mmu_unsync_walk(parent, )) {
bool protected = false;
+   LIST_HEAD(flush_list);
 
-   for_each_sp(pages, sp, parents, i)
+   for_each_sp(pages, sp, parents, i) {
protected |= rmap_write_protect(vcpu, sp->gfn);
+   kvm_mmu_queue_flush_request(sp, _list);
+   }
 
if (protected) {
-   kvm_flush_remote_tlbs(vcpu->kvm);
+   kvm_flush_remote_tlbs_with_list(vcpu->kvm,
+   _list);
flush = false;
}
 
@@ -2710,6 +2721,7 @@ static void kvm_mmu_commit_zap_page(struct kvm *kvm,
struct list_head *invalid_list)
 {
struct kvm_mmu_page *sp, *nsp;
+   LIST_HEAD(flush_list);
 
if (list_empty(invalid_list))
return;
@@ -2723,7 +2735,15 @@ static void kvm_mmu_commit_zap_page(struct kvm *kvm,
 * In addition, kvm_flush_remote_tlbs waits for all vcpus to exit
 * guest mode and/or lockless shadow page table walks.
 */
-   kvm_flush_remote_tlbs(kvm);
+   if (kvm_available_flush_tlb_with_range()) {
+   list_for_each_entry(sp, invalid_list, link)
+   kvm_mmu_queue_flush_request(sp, _list);
+
+   if (!list_empty(_list))
+   kvm_flush_remote_tlbs_with_list(kvm, _list);
+   } else {
+   kvm_flush_remote_tlbs(kvm);
+   }
 
list_for_each_entry_safe(sp, nsp, invalid_list, link) {
WARN_ON(!sp->role.invalid || sp->root_count);
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index 5cbaf7c4a729..a5f967e81429 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -972,6 +972,7 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct 
kvm_mmu_page *sp)
bool host_writable;
gpa_t first_pte_gpa;
int set_spte_ret = 0;
+   LIST_HEAD(flush_list);
 
/* direct kvm_mmu_page can not be unsync. */
BUG_ON(sp->role.direct);
@@ -1032,10 +1033,12 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, 
struct kvm_mmu_page *sp)
 pte_access, PT_PAGE_TABLE_LEVEL,
 gfn, spte_to_pfn(sp->spt[i]),
 true, false, host_writable);
+   if (set_spte_ret && kvm_available_flush_tlb_with_range())
+   kvm_mmu_queue_flush_request(sp, _list);
}
 
if (set_spte_ret & SET_SPTE_NEED_REMOTE_TLB_FLUSH)
-   kvm_flush_remote_tlbs(vcpu->kvm);
+   kvm_flush_remote_tlbs_with_list(vcpu->kvm, _list);
 
return nr_present;
 }
-- 
2.14.4
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH V2 2/13] KVM/MMU: Add tlb flush with range helper function

2018-09-17 Thread Tianyu Lan
This patch is to add wrapper functions for tlb_remote_flush_with_range
callback.

Signed-off-by: Lan Tianyu 
---
 arch/x86/kvm/mmu.c | 48 
 1 file changed, 48 insertions(+)

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index c67f09086378..ac3b748f58f8 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -253,6 +253,54 @@ static void mmu_spte_set(u64 *sptep, u64 spte);
 static union kvm_mmu_page_role
 kvm_mmu_calc_root_page_role(struct kvm_vcpu *vcpu);
 
+
+static inline bool kvm_available_flush_tlb_with_range(void)
+{
+   return kvm_x86_ops->tlb_remote_flush_with_range;
+}
+
+static void kvm_flush_remote_tlbs_with_range(struct kvm *kvm,
+   struct kvm_tlb_range *range)
+{
+   int ret = -ENOTSUPP;
+
+   if (range && kvm_x86_ops->tlb_remote_flush_with_range) {
+   /*
+* Read tlbs_dirty before setting KVM_REQ_TLB_FLUSH in
+* kvm_make_all_cpus_request.
+*/
+   long dirty_count = smp_load_acquire(>tlbs_dirty);
+
+   ret = kvm_x86_ops->tlb_remote_flush_with_range(kvm, range);
+   cmpxchg(>tlbs_dirty, dirty_count, 0);
+   }
+
+   if (ret)
+   kvm_flush_remote_tlbs(kvm);
+}
+
+static void kvm_flush_remote_tlbs_with_list(struct kvm *kvm,
+   struct list_head *flush_list)
+{
+   struct kvm_tlb_range range;
+
+   range.flush_list = flush_list;
+
+   kvm_flush_remote_tlbs_with_range(kvm, );
+}
+
+static void kvm_flush_remote_tlbs_with_address(struct kvm *kvm,
+   u64 start_gfn, u64 pages)
+{
+   struct kvm_tlb_range range;
+
+   range.start_gfn = start_gfn;
+   range.pages = pages;
+   range.flush_list = NULL;
+
+   kvm_flush_remote_tlbs_with_range(kvm, );
+}
+
 void kvm_mmu_set_mmio_spte_mask(u64 mmio_mask, u64 mmio_value)
 {
BUG_ON((mmio_mask & mmio_value) != mmio_value);
-- 
2.14.4
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH V2 4/13] KVM/MMU: Flush tlb directly in the kvm_handle_hva_range()

2018-09-17 Thread Tianyu Lan
This patch is to flush tlb directly in the kvm_handle_hva_range()
when range flush is available.

Signed-off-by: Lan Tianyu 
---
 arch/x86/kvm/mmu.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 822e170881a4..dfd2a0710417 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -1888,6 +1888,13 @@ static int kvm_handle_hva_range(struct kvm *kvm,
 )
ret |= handler(kvm, iterator.rmap, memslot,
   iterator.gfn, iterator.level, 
data);
+
+   if (ret && kvm_available_flush_tlb_with_range()) {
+   kvm_flush_remote_tlbs_with_address(kvm,
+   gfn_start,
+   gfn_end - gfn_start);
+   ret = 0;
+   }
}
}
 
-- 
2.14.4
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH V2 3/13] KVM: Replace old tlb flush function with new one to flush a specified range.

2018-09-17 Thread Tianyu Lan
This patch is to replace kvm_flush_remote_tlbs() with kvm_flush_
remote_tlbs_with_address() in some functions without logic change.

Signed-off-by: Lan Tianyu 
---
 arch/x86/kvm/mmu.c | 33 ++---
 arch/x86/kvm/paging_tmpl.h |  3 ++-
 2 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index ac3b748f58f8..822e170881a4 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -1482,8 +1482,12 @@ static bool __drop_large_spte(struct kvm *kvm, u64 
*sptep)
 
 static void drop_large_spte(struct kvm_vcpu *vcpu, u64 *sptep)
 {
-   if (__drop_large_spte(vcpu->kvm, sptep))
-   kvm_flush_remote_tlbs(vcpu->kvm);
+   if (__drop_large_spte(vcpu->kvm, sptep)) {
+   struct kvm_mmu_page *sp = page_header(__pa(sptep));
+
+   kvm_flush_remote_tlbs_with_address(vcpu->kvm, sp->gfn,
+   KVM_PAGES_PER_HPAGE(sp->role.level));
+   }
 }
 
 /*
@@ -1770,7 +1774,7 @@ static int kvm_set_pte_rmapp(struct kvm *kvm, struct 
kvm_rmap_head *rmap_head,
}
 
if (need_flush)
-   kvm_flush_remote_tlbs(kvm);
+   kvm_flush_remote_tlbs_with_address(kvm, gfn, 1);
 
return 0;
 }
@@ -1951,7 +1955,8 @@ static void rmap_recycle(struct kvm_vcpu *vcpu, u64 
*spte, gfn_t gfn)
rmap_head = gfn_to_rmap(vcpu->kvm, gfn, sp);
 
kvm_unmap_rmapp(vcpu->kvm, rmap_head, NULL, gfn, sp->role.level, 0);
-   kvm_flush_remote_tlbs(vcpu->kvm);
+   kvm_flush_remote_tlbs_with_address(vcpu->kvm, sp->gfn,
+   KVM_PAGES_PER_HPAGE(sp->role.level));
 }
 
 int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end)
@@ -2467,7 +2472,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct 
kvm_vcpu *vcpu,
account_shadowed(vcpu->kvm, sp);
if (level == PT_PAGE_TABLE_LEVEL &&
  rmap_write_protect(vcpu, gfn))
-   kvm_flush_remote_tlbs(vcpu->kvm);
+   kvm_flush_remote_tlbs_with_address(vcpu->kvm, gfn, 1);
 
if (level > PT_PAGE_TABLE_LEVEL && need_sync)
flush |= kvm_sync_pages(vcpu, gfn, _list);
@@ -2587,7 +2592,7 @@ static void validate_direct_spte(struct kvm_vcpu *vcpu, 
u64 *sptep,
return;
 
drop_parent_pte(child, sptep);
-   kvm_flush_remote_tlbs(vcpu->kvm);
+   kvm_flush_remote_tlbs_with_address(vcpu->kvm, child->gfn, 1);
}
 }
 
@@ -3011,8 +3016,10 @@ static int mmu_set_spte(struct kvm_vcpu *vcpu, u64 
*sptep, unsigned pte_access,
ret = RET_PF_EMULATE;
kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
}
+
if (set_spte_ret & SET_SPTE_NEED_REMOTE_TLB_FLUSH || flush)
-   kvm_flush_remote_tlbs(vcpu->kvm);
+   kvm_flush_remote_tlbs_with_address(vcpu->kvm, gfn,
+   KVM_PAGES_PER_HPAGE(level));
 
if (unlikely(is_mmio_spte(*sptep)))
ret = RET_PF_EMULATE;
@@ -5621,7 +5628,8 @@ void kvm_mmu_slot_remove_write_access(struct kvm *kvm,
 * on PT_WRITABLE_MASK anymore.
 */
if (flush)
-   kvm_flush_remote_tlbs(kvm);
+   kvm_flush_remote_tlbs_with_address(kvm, memslot->base_gfn,
+   memslot->npages);
 }
 
 static bool kvm_mmu_zap_collapsible_spte(struct kvm *kvm,
@@ -5685,7 +5693,8 @@ void kvm_mmu_slot_leaf_clear_dirty(struct kvm *kvm,
 * dirty_bitmap.
 */
if (flush)
-   kvm_flush_remote_tlbs(kvm);
+   kvm_flush_remote_tlbs_with_address(kvm, memslot->base_gfn,
+   memslot->npages);
 }
 EXPORT_SYMBOL_GPL(kvm_mmu_slot_leaf_clear_dirty);
 
@@ -5703,7 +5712,8 @@ void kvm_mmu_slot_largepage_remove_write_access(struct 
kvm *kvm,
lockdep_assert_held(>slots_lock);
 
if (flush)
-   kvm_flush_remote_tlbs(kvm);
+   kvm_flush_remote_tlbs_with_address(kvm, memslot->base_gfn,
+   memslot->npages);
 }
 EXPORT_SYMBOL_GPL(kvm_mmu_slot_largepage_remove_write_access);
 
@@ -5720,7 +5730,8 @@ void kvm_mmu_slot_set_dirty(struct kvm *kvm,
 
/* see kvm_mmu_slot_leaf_clear_dirty */
if (flush)
-   kvm_flush_remote_tlbs(kvm);
+   kvm_flush_remote_tlbs_with_address(kvm, memslot->base_gfn,
+   memslot->npages);
 }
 EXPORT_SYMBOL_GPL(kvm_mmu_slot_set_dirty);
 
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index 14ffd973df54..708a5e44861a 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -893,7 +893,8 @@ static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva, 
hpa_t root_hpa)
pte_gpa += (sptep - sp->spt) * sizeof(pt_element_t);
 
if (mmu_page_zap_pte(vcpu->kvm, sp, sptep))

[PATCH V2 00/13] x86/KVM/Hyper-v: Add HV ept tlb range flush hypercall support in KVM

2018-09-17 Thread Tianyu Lan


For nested memory virtualization, Hyper-v doesn't set write-protect
L1 hypervisor EPT page directory and page table node to track changes 
while it relies on guest to tell it changes via HvFlushGuestAddressLlist
hypercall. HvFlushGuestAddressLlist hypercall provides a way to flush
EPT page table with ranges which are specified by L1 hypervisor.

If L1 hypervisor uses INVEPT or HvFlushGuestAddressSpace hypercall to
flush EPT tlb, Hyper-V will invalidate associated EPT shadow page table
and sync L1's EPT table when next EPT page fault is triggered.
HvFlushGuestAddressLlist hypercall helps to avoid such redundant EPT
page fault and synchronization of shadow page table.

Change since v1:
   1) Convert "end_gfn" of struct kvm_tlb_range to "pages" in order
  to avoid confusion as to whether "end_gfn" is inclusive or exlusive.
   2) Add hyperv tlb range struct and replace kvm tlb range struct
  with new struct in order to avoid using kvm struct in the hyperv
  code directly.

Lan Tianyu (13):
  KVM: Add tlb_remote_flush_with_range callback in kvm_x86_ops
  KVM/MMU: Add tlb flush with range helper function
  KVM: Replace old tlb flush function with new one to flush a specified
range.
  KVM/MMU: Flush tlb directly in the kvm_handle_hva_range()
  KVM/MMU: Flush tlb directly in the kvm_zap_gfn_range()
  KVM/MMU: Flush tlb directly in kvm_mmu_zap_collapsible_spte()
  KVM: Add flush_link and parent_pte in the struct kvm_mmu_page
  KVM: Add spte's point in the struct kvm_mmu_page
  KVM/MMU: Replace tlb flush function with range list flush function
  x86/hyper-v: Add HvFlushGuestAddressList hypercall support
  x86/Hyper-v: Add trace in the
hyperv_nested_flush_guest_mapping_range()
  KVM/VMX: Change hv flush logic when ept tables are mismatched.
  KVM/VMX: Add hv tlb range flush support

 arch/x86/hyperv/nested.c| 104 ++
 arch/x86/include/asm/hyperv-tlfs.h  |  17 +
 arch/x86/include/asm/kvm_host.h |  10 +++
 arch/x86/include/asm/mshyperv.h |  16 
 arch/x86/include/asm/trace/hyperv.h |  14 
 arch/x86/kvm/mmu.c  | 143 +++-
 arch/x86/kvm/paging_tmpl.h  |  16 +++-
 arch/x86/kvm/vmx.c  |  65 +---
 8 files changed, 354 insertions(+), 31 deletions(-)

-- 
2.14.4
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH V2 1/13] KVM: Add tlb_remote_flush_with_range callback in kvm_x86_ops

2018-09-17 Thread Tianyu Lan
Add flush range call back in the kvm_x86_ops and platform can use it
to register its associated function. The parameter "kvm_tlb_range"
accepts a single range and flush list which contains a list of ranges.

Signed-off-by: Lan Tianyu 
---
Change since v1:
   Change "end_gfn" to "pages" to aviod confusion as to whether
"end_gfn" is inclusive or exlusive.
---
 arch/x86/include/asm/kvm_host.h | 8 
 1 file changed, 8 insertions(+)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 8e90488c3d56..a6b77978502e 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -402,6 +402,12 @@ struct kvm_mmu {
u64 pdptrs[4]; /* pae */
 };
 
+struct kvm_tlb_range {
+   u64 start_gfn;
+   u64 pages;
+   struct list_head *flush_list;
+};
+
 enum pmc_type {
KVM_PMC_GP = 0,
KVM_PMC_FIXED,
@@ -991,6 +997,8 @@ struct kvm_x86_ops {
 
void (*tlb_flush)(struct kvm_vcpu *vcpu, bool invalidate_gpa);
int  (*tlb_remote_flush)(struct kvm *kvm);
+   int  (*tlb_remote_flush_with_range)(struct kvm *kvm,
+   struct kvm_tlb_range *range);
 
/*
 * Flush any TLB entries associated with the given GVA.
-- 
2.14.4
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 1/13] KVM: Add tlb_remote_flush_with_range callback in kvm_x86_ops

2018-09-12 Thread Tianyu Lan
Hi Sean:
Thanks for your review.

On 9/10/2018 10:21 PM, Sean Christopherson wrote:
> On Mon, 2018-09-10 at 08:38 +0000, Tianyu Lan wrote:
>> Add flush range call back in the kvm_x86_ops and platform can use it
>> to register its associated function. The parameter "kvm_tlb_range"
>> accepts a single range and flush list which contains a list of ranges.
>>
>> Signed-off-by: Lan Tianyu 
>> ---
>>   arch/x86/include/asm/kvm_host.h | 8 
>>   1 file changed, 8 insertions(+)
>>
>> diff --git a/arch/x86/include/asm/kvm_host.h 
>> b/arch/x86/include/asm/kvm_host.h
>> index e12916e7c2fb..dcdf8cc16388 100644
>> --- a/arch/x86/include/asm/kvm_host.h
>> +++ b/arch/x86/include/asm/kvm_host.h
>> @@ -402,6 +402,12 @@ struct kvm_mmu {
>>      u64 pdptrs[4]; /* pae */
>>   };
>>   
>> +struct kvm_tlb_range {
>> +u64 start_gfn;
>> +u64 end_gfn;
> 
> IMO this struct and all functions should pass around the number of pages
> instead of end_gfn to avoid confusion as to whether end_gfn is inclusive
> or exlusive.

That's good suggestion. Thanks.

> 
>> +struct list_head *flush_list;
>> +};
>> +
>>   enum pmc_type {
>>      KVM_PMC_GP = 0,
>>      KVM_PMC_FIXED,
>> @@ -991,6 +997,8 @@ struct kvm_x86_ops {
>>   
>>      void (*tlb_flush)(struct kvm_vcpu *vcpu, bool invalidate_gpa);
>>      int  (*tlb_remote_flush)(struct kvm *kvm);
>> +int  (*tlb_remote_flush_with_range)(struct kvm *kvm,
>> +struct kvm_tlb_range *range);
>>   
>>      /*
>>       * Flush any TLB entries associated with the given GVA.
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 10/13] x86/hyper-v: Add HvFlushGuestAddressList hypercall support

2018-09-12 Thread Tianyu Lan
Hi Michael:
Thanks for your review.

On 9/12/2018 8:22 AM, Michael Kelley (EOSG) wrote:
> From: Tianyu Lan  Sent: Monday, September 10, 2018 1:39 AM
>> +
>> +int hyperv_flush_guest_mapping_range(u64 as, struct kvm_tlb_range *range)
> 
> I'm really concerned about defining the Hyper-V function to flush
> guest mappings in terms of a KVM struct definition.  Your patch puts
> this function in arch/x86/hyperv/nested.c.  I haven't investigated all
> the details, but on its face this approach seems like it would cause
> trouble in the long run, and it doesn't support the case of a
> hypervisor other than KVM running at L1.
> 
> I know that KVM code has taken a dependency on Hyper-V types and
> code, but that's because KVM is emulating a lot of Hyper-V functionality
> and it's taking advantage of Hyper-V enlightenments.  Is there a top
> level reason I haven't thought of for Hyper-V code to take a
> dependency on KVM definitions?  I would think we want Hyper-V
> code to be generic, using Hyper-V data structure definitions.  Then in
> keeping with what's already been done, KVM code would use those
> definitions where it needs to make calls to Hyper-V code.
>

I think KVM is only one kernel-based hypervisor and is only caller of 
nested hypercalls. So I reused KVM data structure in the new function.
I will make it more general in the next version.

>> +{
>> +struct kvm_mmu_page *sp;
>> +struct hv_guest_mapping_flush_list **flush_pcpu;
>> +struct hv_guest_mapping_flush_list *flush;
>> +u64 status = 0;
>> +unsigned long flags;
>> +int ret = -ENOTSUPP;
>> +int gpa_n = 0;
>> +
>> +if (!hv_hypercall_pg)
>> +goto fault;
>> +
>> +local_irq_save(flags);
>> +
>> +flush_pcpu = (struct hv_guest_mapping_flush_list **)
>> +this_cpu_ptr(hyperv_pcpu_input_arg);
>> +
>> +flush = *flush_pcpu;
>> +if (unlikely(!flush)) {
>> +local_irq_restore(flags);
>> +goto fault;
>> +}
>> +
>> +flush->address_space = as;
>> +flush->flags = 0;
>> +
>> +if (!range->flush_list) {
>> +gpa_n = fill_flush_list(flush->gpa_list, gpa_n,
>> +range->start_gfn, range->end_gfn);
>> +} else {
>> +list_for_each_entry(sp, range->flush_list,
>> +flush_link) {
>> +u64 end_gfn = sp->gfn +
>> +KVM_PAGES_PER_HPAGE(sp->role.level) - 1;
>> +gpa_n = fill_flush_list(flush->gpa_list, gpa_n,
>> +sp->gfn, end_gfn);
>> +}
> 
> Per the previous comment, if this loop really needs to walk a KVM
> data structure, look for a different way to organize things so that
> the handling of KVM-specific data structures is in code that’s part
> of KVM, rather than in Hyper-V code.
> 
> Michael
> 
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 5/13] KVM/MMU: Flush tlb directly in the kvm_zap_gfn_range()

2018-09-10 Thread Tianyu Lan
Originally, flush tlb is done by slot_handle_level_range(). This patch
is to flush tlb directly in the kvm_zap_gfn_range() when range
flush is available.

Signed-off-by: Lan Tianyu 
---
 arch/x86/kvm/mmu.c | 15 ---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index cadb6a0b5247..9ae5887c8d1c 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -5583,6 +5583,7 @@ void kvm_zap_gfn_range(struct kvm *kvm, gfn_t gfn_start, 
gfn_t gfn_end)
 {
struct kvm_memslots *slots;
struct kvm_memory_slot *memslot;
+   bool flush = false;
int i;
 
spin_lock(>mmu_lock);
@@ -5590,18 +5591,26 @@ void kvm_zap_gfn_range(struct kvm *kvm, gfn_t 
gfn_start, gfn_t gfn_end)
slots = __kvm_memslots(kvm, i);
kvm_for_each_memslot(memslot, slots) {
gfn_t start, end;
+   bool flush_tlb = true;
 
start = max(gfn_start, memslot->base_gfn);
end = min(gfn_end, memslot->base_gfn + memslot->npages);
if (start >= end)
continue;
 
-   slot_handle_level_range(kvm, memslot, kvm_zap_rmapp,
-   PT_PAGE_TABLE_LEVEL, 
PT_MAX_HUGEPAGE_LEVEL,
-   start, end - 1, true);
+   if (kvm_available_flush_tlb_with_range())
+   flush_tlb = false;
+
+   flush = slot_handle_level_range(kvm, memslot,
+   kvm_zap_rmapp, PT_PAGE_TABLE_LEVEL,
+   PT_MAX_HUGEPAGE_LEVEL, start,
+   end - 1, flush_tlb);
}
}
 
+   if (flush && kvm_available_flush_tlb_with_range())
+   kvm_flush_remote_tlbs_with_address(kvm, gfn_start, gfn_end);
+
spin_unlock(>mmu_lock);
 }
 
-- 
2.14.4
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 10/13] x86/hyper-v: Add HvFlushGuestAddressList hypercall support

2018-09-10 Thread Tianyu Lan
Hyper-V provides HvFlushGuestAddressList() hypercall to flush EPT tlb
with specified ranges. This patch is to add the hypercall support.

Signed-off-by: Lan Tianyu 
---
 arch/x86/hyperv/nested.c   | 110 +
 arch/x86/include/asm/hyperv-tlfs.h |  17 ++
 arch/x86/include/asm/mshyperv.h|   8 +++
 3 files changed, 135 insertions(+)

diff --git a/arch/x86/hyperv/nested.c b/arch/x86/hyperv/nested.c
index b8e60cc50461..bb716ed94320 100644
--- a/arch/x86/hyperv/nested.c
+++ b/arch/x86/hyperv/nested.c
@@ -7,15 +7,32 @@
  *
  * Author : Lan Tianyu 
  */
+#define pr_fmt(fmt)  "Hyper-V: " fmt
 
 
 #include 
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
+/*
+ *  MAX_FLUSH_PAGES = "additional_pages" + 1. It's limited
+ *  by the bitwidth of "additional_pages" in union hv_gpa_page_range.
+ */
+#define MAX_FLUSH_PAGES (2048)
+
+/*
+ * All input flush parameters are in single page. The max flush count
+ * is equal with how many entries of union hv_gpa_page_range can be
+ * populated in the input parameter page. MAX_FLUSH_REP_COUNT
+ * = (4096 - 16) / 8. (“Page Size” - "Address Space" - "Flags") /
+ * "GPA Range".
+ */
+#define MAX_FLUSH_REP_COUNT (510)
+
 int hyperv_flush_guest_mapping(u64 as)
 {
struct hv_guest_mapping_flush **flush_pcpu;
@@ -54,3 +71,96 @@ int hyperv_flush_guest_mapping(u64 as)
return ret;
 }
 EXPORT_SYMBOL_GPL(hyperv_flush_guest_mapping);
+
+static inline int fill_flush_list(union hv_gpa_page_range gpa_list[],
+   int offset, u64 start_gfn, u64 end_gfn)
+{
+   int gpa_n = offset;
+   u64 cur = start_gfn;
+   u64 pages = end_gfn - start_gfn + 1;
+   u64 additional_pages;
+
+   if (end_gfn < start_gfn)
+   return -EINVAL;
+
+   do {
+   if (gpa_n == MAX_FLUSH_REP_COUNT) {
+   pr_warn("Request exceeds HvFlushGuestList max flush 
count.\n");
+   return -ENOSPC;
+   }
+
+   if (pages > MAX_FLUSH_PAGES) {
+   additional_pages = MAX_FLUSH_PAGES - 1;
+   pages -= MAX_FLUSH_PAGES;
+   } else {
+   additional_pages = pages - 1;
+   pages = 0;
+   }
+
+   gpa_list[gpa_n].page.additional_pages = additional_pages;
+   gpa_list[gpa_n].page.largepage = false;
+   gpa_list[gpa_n].page.basepfn = cur;
+
+   cur += additional_pages + 1;
+   gpa_n++;
+   } while (pages > 0);
+
+   return gpa_n;
+}
+
+int hyperv_flush_guest_mapping_range(u64 as, struct kvm_tlb_range *range)
+{
+   struct kvm_mmu_page *sp;
+   struct hv_guest_mapping_flush_list **flush_pcpu;
+   struct hv_guest_mapping_flush_list *flush;
+   u64 status = 0;
+   unsigned long flags;
+   int ret = -ENOTSUPP;
+   int gpa_n = 0;
+
+   if (!hv_hypercall_pg)
+   goto fault;
+
+   local_irq_save(flags);
+
+   flush_pcpu = (struct hv_guest_mapping_flush_list **)
+   this_cpu_ptr(hyperv_pcpu_input_arg);
+
+   flush = *flush_pcpu;
+   if (unlikely(!flush)) {
+   local_irq_restore(flags);
+   goto fault;
+   }
+
+   flush->address_space = as;
+   flush->flags = 0;
+
+   if (!range->flush_list) {
+   gpa_n = fill_flush_list(flush->gpa_list, gpa_n,
+   range->start_gfn, range->end_gfn);
+   } else {
+   list_for_each_entry(sp, range->flush_list,
+   flush_link) {
+   u64 end_gfn = sp->gfn +
+   KVM_PAGES_PER_HPAGE(sp->role.level) - 1;
+   gpa_n = fill_flush_list(flush->gpa_list, gpa_n,
+   sp->gfn, end_gfn);
+   }
+   }
+
+   if (gpa_n < 0) {
+   local_irq_restore(flags);
+   goto fault;
+   }
+
+   status = hv_do_rep_hypercall(HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_LIST,
+gpa_n, 0, flush, NULL);
+
+   local_irq_restore(flags);
+
+   if (!(status & HV_HYPERCALL_RESULT_MASK))
+   ret = 0;
+fault:
+   return ret;
+}
+EXPORT_SYMBOL_GPL(hyperv_flush_guest_mapping_range);
diff --git a/arch/x86/include/asm/hyperv-tlfs.h 
b/arch/x86/include/asm/hyperv-tlfs.h
index e977b6b3a538..512f22b4 100644
--- a/arch/x86/include/asm/hyperv-tlfs.h
+++ b/arch/x86/include/asm/hyperv-tlfs.h
@@ -353,6 +353,7 @@ struct hv_tsc_emulation_status {
 #define HVCALL_POST_MESSAGE0x005c
 #define HVCALL_SIGNAL_EVENT0x005d
 #define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE 0x00af
+#define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_LIST 0x00b0
 
 #define HV_X64_MSR_VP_ASSIST_PAGE_ENABLE   0x0001
 #define HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_SHIFT12
@@ -750,6 +751,22 @@ struct 

[PATCH 11/13] x86/Hyper-v: Add trace in the hyperv_nested_flush_guest_mapping_range()

2018-09-10 Thread Tianyu Lan
This patch is to trace log in the hyperv_nested_flush_
guest_mapping_range().

Signed-off-by: Lan Tianyu 
---
 arch/x86/hyperv/nested.c|  1 +
 arch/x86/include/asm/trace/hyperv.h | 14 ++
 2 files changed, 15 insertions(+)

diff --git a/arch/x86/hyperv/nested.c b/arch/x86/hyperv/nested.c
index bb716ed94320..90e5eee1b410 100644
--- a/arch/x86/hyperv/nested.c
+++ b/arch/x86/hyperv/nested.c
@@ -161,6 +161,7 @@ int hyperv_flush_guest_mapping_range(u64 as, struct 
kvm_tlb_range *range)
if (!(status & HV_HYPERCALL_RESULT_MASK))
ret = 0;
 fault:
+   trace_hyperv_nested_flush_guest_mapping_range(as, ret);
return ret;
 }
 EXPORT_SYMBOL_GPL(hyperv_flush_guest_mapping_range);
diff --git a/arch/x86/include/asm/trace/hyperv.h 
b/arch/x86/include/asm/trace/hyperv.h
index 2e6245a023ef..ace464f09681 100644
--- a/arch/x86/include/asm/trace/hyperv.h
+++ b/arch/x86/include/asm/trace/hyperv.h
@@ -42,6 +42,20 @@ TRACE_EVENT(hyperv_nested_flush_guest_mapping,
TP_printk("address space %llx ret %d", __entry->as, __entry->ret)
);
 
+TRACE_EVENT(hyperv_nested_flush_guest_mapping_range,
+   TP_PROTO(u64 as, int ret),
+   TP_ARGS(as, ret),
+
+   TP_STRUCT__entry(
+   __field(u64, as)
+   __field(int, ret)
+   ),
+   TP_fast_assign(__entry->as = as;
+  __entry->ret = ret;
+   ),
+   TP_printk("address space %llx ret %d", __entry->as, __entry->ret)
+   );
+
 TRACE_EVENT(hyperv_send_ipi_mask,
TP_PROTO(const struct cpumask *cpus,
 int vector),
-- 
2.14.4
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 8/13] KVM: Add spte's point in the struct kvm_mmu_page

2018-09-10 Thread Tianyu Lan
It's necessary to check whether mmu page is last or large page when add
mmu page into flush list. "spte" is needed for such check and so add
spte point in the struct kvm_mmu_page.

Signed-off-by: Lan Tianyu 
---
 arch/x86/include/asm/kvm_host.h | 1 +
 arch/x86/kvm/mmu.c  | 5 +
 arch/x86/kvm/paging_tmpl.h  | 2 ++
 3 files changed, 8 insertions(+)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index acdad302612a..03c7290f4187 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -296,6 +296,7 @@ struct kvm_mmu_page {
int root_count;  /* Currently serving as active root */
unsigned int unsync_children;
struct kvm_rmap_head parent_ptes; /* rmap pointers to parent sptes */
+   u64 *sptep;
 
/* The page is obsolete if mmu_valid_gen != kvm->arch.mmu_valid_gen.  */
unsigned long mmu_valid_gen;
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 167ecfbab9bd..73e19ce589e7 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -3167,6 +3167,7 @@ static int __direct_map(struct kvm_vcpu *vcpu, int write, 
int map_writable,
pseudo_gfn = base_addr >> PAGE_SHIFT;
sp = kvm_mmu_get_page(vcpu, pseudo_gfn, iterator.addr,
  iterator.level - 1, 1, ACC_ALL);
+   sp->sptep = iterator.sptep;
 
link_shadow_page(vcpu, iterator.sptep, sp);
}
@@ -3604,6 +3605,7 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu)
sp = kvm_mmu_get_page(vcpu, 0, 0,
vcpu->arch.mmu.shadow_root_level, 1, ACC_ALL);
++sp->root_count;
+   sp->sptep = NULL;
spin_unlock(>kvm->mmu_lock);
vcpu->arch.mmu.root_hpa = __pa(sp->spt);
} else if (vcpu->arch.mmu.shadow_root_level == PT32E_ROOT_LEVEL) {
@@ -3620,6 +3622,7 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu)
i << 30, PT32_ROOT_LEVEL, 1, ACC_ALL);
root = __pa(sp->spt);
++sp->root_count;
+   sp->sptep = NULL;
spin_unlock(>kvm->mmu_lock);
vcpu->arch.mmu.pae_root[i] = root | PT_PRESENT_MASK;
}
@@ -3660,6 +3663,7 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu)
vcpu->arch.mmu.shadow_root_level, 0, ACC_ALL);
root = __pa(sp->spt);
++sp->root_count;
+   sp->sptep = NULL;
spin_unlock(>kvm->mmu_lock);
vcpu->arch.mmu.root_hpa = root;
return 0;
@@ -3697,6 +3701,7 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu)
  0, ACC_ALL);
root = __pa(sp->spt);
++sp->root_count;
+   sp->sptep = NULL;
spin_unlock(>kvm->mmu_lock);
 
vcpu->arch.mmu.pae_root[i] = root | pm_mask;
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index f45f1a5fbfe8..bb8c2cdf70c3 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -632,6 +632,7 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
table_gfn = gw->table_gfn[it.level - 2];
sp = kvm_mmu_get_page(vcpu, table_gfn, addr, it.level-1,
  false, access);
+   sp->sptep = it.sptep;
}
 
/*
@@ -662,6 +663,7 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
 
sp = kvm_mmu_get_page(vcpu, direct_gfn, addr, it.level-1,
  true, direct_access);
+   sp->sptep = it.sptep;
link_shadow_page(vcpu, it.sptep, sp);
}
 
-- 
2.14.4
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 9/13] KVM/MMU: Replace tlb flush function with range list flush function

2018-09-10 Thread Tianyu Lan
This patch is to use range list flush function in the
mmu_sync_children(), kvm_mmu_commit_zap_page() and
FNAME(sync_page)().

Signed-off-by: Lan Tianyu 
---
 arch/x86/kvm/mmu.c | 26 +++---
 arch/x86/kvm/paging_tmpl.h |  5 -
 2 files changed, 27 insertions(+), 4 deletions(-)

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 73e19ce589e7..a071da797a15 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -1092,6 +1092,13 @@ static void update_gfn_disallow_lpage_count(struct 
kvm_memory_slot *slot,
}
 }
 
+static void kvm_mmu_queue_flush_request(struct kvm_mmu_page *sp,
+   struct list_head *flush_list)
+{
+   if (sp->sptep && is_last_spte(*sp->sptep, sp->role.level))
+   list_add(>flush_link, flush_list);
+}
+
 void kvm_mmu_gfn_disallow_lpage(struct kvm_memory_slot *slot, gfn_t gfn)
 {
update_gfn_disallow_lpage_count(slot, gfn, 1);
@@ -2373,12 +2380,16 @@ static void mmu_sync_children(struct kvm_vcpu *vcpu,
 
while (mmu_unsync_walk(parent, )) {
bool protected = false;
+   LIST_HEAD(flush_list);
 
-   for_each_sp(pages, sp, parents, i)
+   for_each_sp(pages, sp, parents, i) {
protected |= rmap_write_protect(vcpu, sp->gfn);
+   kvm_mmu_queue_flush_request(sp, _list);
+   }
 
if (protected) {
-   kvm_flush_remote_tlbs(vcpu->kvm);
+   kvm_flush_remote_tlbs_with_list(vcpu->kvm,
+   _list);
flush = false;
}
 
@@ -2715,6 +2726,7 @@ static void kvm_mmu_commit_zap_page(struct kvm *kvm,
struct list_head *invalid_list)
 {
struct kvm_mmu_page *sp, *nsp;
+   LIST_HEAD(flush_list);
 
if (list_empty(invalid_list))
return;
@@ -2728,7 +2740,15 @@ static void kvm_mmu_commit_zap_page(struct kvm *kvm,
 * In addition, kvm_flush_remote_tlbs waits for all vcpus to exit
 * guest mode and/or lockless shadow page table walks.
 */
-   kvm_flush_remote_tlbs(kvm);
+   if (kvm_available_flush_tlb_with_range()) {
+   list_for_each_entry(sp, invalid_list, link)
+   kvm_mmu_queue_flush_request(sp, _list);
+
+   if (!list_empty(_list))
+   kvm_flush_remote_tlbs_with_list(kvm, _list);
+   } else {
+   kvm_flush_remote_tlbs(kvm);
+   }
 
list_for_each_entry_safe(sp, nsp, invalid_list, link) {
WARN_ON(!sp->role.invalid || sp->root_count);
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index bb8c2cdf70c3..aa450e0596a4 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -976,6 +976,7 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct 
kvm_mmu_page *sp)
bool host_writable;
gpa_t first_pte_gpa;
int set_spte_ret = 0;
+   LIST_HEAD(flush_list);
 
/* direct kvm_mmu_page can not be unsync. */
BUG_ON(sp->role.direct);
@@ -1036,10 +1037,12 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, 
struct kvm_mmu_page *sp)
 pte_access, PT_PAGE_TABLE_LEVEL,
 gfn, spte_to_pfn(sp->spt[i]),
 true, false, host_writable);
+   if (set_spte_ret && kvm_available_flush_tlb_with_range())
+   kvm_mmu_queue_flush_request(sp, _list);
}
 
if (set_spte_ret & SET_SPTE_NEED_REMOTE_TLB_FLUSH)
-   kvm_flush_remote_tlbs(vcpu->kvm);
+   kvm_flush_remote_tlbs_with_list(vcpu->kvm, _list);
 
return nr_present;
 }
-- 
2.14.4
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 6/13] KVM/MMU: Flush tlb directly in kvm_mmu_zap_collapsible_spte()

2018-09-10 Thread Tianyu Lan
kvm_mmu_zap_collapsible_spte() returns flush request to the
slot_handle_leaf() and the latter does flush on demand. When
range flush is available, make kvm_mmu_zap_collapsible_spte()
to flush tlb with range directly to avoid returning range back
to slot_handle_leaf().

Signed-off-by: Lan Tianyu 
---
 arch/x86/kvm/mmu.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 9ae5887c8d1c..167ecfbab9bd 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -5678,7 +5678,17 @@ static bool kvm_mmu_zap_collapsible_spte(struct kvm *kvm,
!kvm_is_reserved_pfn(pfn) &&
PageTransCompoundMap(pfn_to_page(pfn))) {
drop_spte(kvm, sptep);
-   need_tlb_flush = 1;
+
+   if (kvm_available_flush_tlb_with_range()) {
+   u64 gfn_end = sp->gfn +
+   KVM_PAGES_PER_HPAGE(sp->role.level) - 1;
+
+   kvm_flush_remote_tlbs_with_address(kvm, sp->gfn,
+   gfn_end);
+   } else {
+   need_tlb_flush = 1;
+   }
+
goto restart;
}
}
-- 
2.14.4
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 4/13] KVM/MMU: Flush tlb directly in the kvm_handle_hva_range()

2018-09-10 Thread Tianyu Lan
This patch is to flush tlb directly in the kvm_handle_hva_range()
when range flush is available.

Signed-off-by: Lan Tianyu 
---
 arch/x86/kvm/mmu.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 0ee310bad2c6..cadb6a0b5247 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -1888,6 +1888,12 @@ static int kvm_handle_hva_range(struct kvm *kvm,
 )
ret |= handler(kvm, iterator.rmap, memslot,
   iterator.gfn, iterator.level, 
data);
+
+   if (ret && kvm_available_flush_tlb_with_range()) {
+   kvm_flush_remote_tlbs_with_address(kvm,
+   gfn_start, gfn_end - 1);
+   ret = 0;
+   }
}
}
 
-- 
2.14.4
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 7/13] KVM: Add flush_link and parent_pte in the struct kvm_mmu_page

2018-09-10 Thread Tianyu Lan
PV EPT tlb flush function will accept a list of flush ranges and
use struct kvm_mmu_page as the list entry.

Signed-off-by: Lan Tianyu 
---
 arch/x86/include/asm/kvm_host.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index dcdf8cc16388..acdad302612a 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -279,6 +279,7 @@ struct kvm_rmap_head {
 
 struct kvm_mmu_page {
struct list_head link;
+   struct list_head flush_link;
struct hlist_node hash_link;
 
/*
-- 
2.14.4
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 2/13] KVM/MMU: Add tlb flush with range helper function

2018-09-10 Thread Tianyu Lan
This patch is to add wrapper functions for tlb_remote_flush_with_range
callback.

Signed-off-by: Lan Tianyu 
---
 arch/x86/kvm/mmu.c | 48 
 1 file changed, 48 insertions(+)

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 456d4d0f7eb7..8cf47befc0f2 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -253,6 +253,54 @@ static void mmu_spte_set(u64 *sptep, u64 spte);
 static union kvm_mmu_page_role
 kvm_mmu_calc_root_page_role(struct kvm_vcpu *vcpu);
 
+
+static inline bool kvm_available_flush_tlb_with_range(void)
+{
+   return kvm_x86_ops->tlb_remote_flush_with_range;
+}
+
+static void kvm_flush_remote_tlbs_with_range(struct kvm *kvm,
+   struct kvm_tlb_range *range)
+{
+   int ret = -ENOTSUPP;
+
+   if (range && kvm_x86_ops->tlb_remote_flush_with_range) {
+   /*
+* Read tlbs_dirty before setting KVM_REQ_TLB_FLUSH in
+* kvm_make_all_cpus_request.
+*/
+   long dirty_count = smp_load_acquire(>tlbs_dirty);
+
+   ret = kvm_x86_ops->tlb_remote_flush_with_range(kvm, range);
+   cmpxchg(>tlbs_dirty, dirty_count, 0);
+   }
+
+   if (ret)
+   kvm_flush_remote_tlbs(kvm);
+}
+
+static void kvm_flush_remote_tlbs_with_list(struct kvm *kvm,
+   struct list_head *flush_list)
+{
+   struct kvm_tlb_range range;
+
+   range.flush_list = flush_list;
+
+   kvm_flush_remote_tlbs_with_range(kvm, );
+}
+
+static void kvm_flush_remote_tlbs_with_address(struct kvm *kvm,
+   u64 start_gfn, u64 end_gfn)
+{
+   struct kvm_tlb_range range;
+
+   range.start_gfn = start_gfn;
+   range.end_gfn = end_gfn;
+   range.flush_list = NULL;
+
+   kvm_flush_remote_tlbs_with_range(kvm, );
+}
+
 void kvm_mmu_set_mmio_spte_mask(u64 mmio_mask, u64 mmio_value)
 {
BUG_ON((mmio_mask & mmio_value) != mmio_value);
-- 
2.14.4
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 00/13] x86/KVM/Hyper-v: Add HV ept tlb range flush hypercall support in KVM

2018-09-10 Thread Tianyu Lan
For nested memory virtualization, Hyper-v doesn't set write-protect
L1 hypervisor EPT page directory and page table node to track changes 
while it relies on guest to tell it changes via HvFlushGuestAddressLlist
hypercall. HvFlushGuestAddressLlist hypercall provides a way to flush
EPT page table with ranges which are specified by L1 hypervisor.

If L1 hypervisor uses INVEPT or HvFlushGuestAddressSpace hypercall to
flush EPT tlb, Hyper-V will invalidate associated EPT shadow page table
and sync L1's EPT table when next EPT page fault is triggered.
HvFlushGuestAddressLlist hypercall helps to avoid such redundant EPT
page fault and synchronization of shadow page table.

Lan Tianyu (13):
  KVM: Add tlb_remote_flush_with_range callback in kvm_x86_ops
  KVM/MMU: Add tlb flush with range helper function
  KVM: Replace old tlb flush function with new one to flush a specified
range.
  KVM/MMU: Flush tlb directly in the kvm_handle_hva_range()
  KVM/MMU: Flush tlb directly in the kvm_zap_gfn_range()
  KVM/MMU: Flush tlb directly in kvm_mmu_zap_collapsible_spte()
  KVM: Add flush_link and parent_pte in the struct kvm_mmu_page
  KVM: Add spte's point in the struct kvm_mmu_page
  KVM/MMU: Replace tlb flush function with range list flush function
  x86/hyper-v: Add HvFlushGuestAddressList hypercall support
  x86/Hyper-v: Add trace in the
hyperv_nested_flush_guest_mapping_range()
  KVM/VMX: Change hv flush logic when ept tables are mismatched.
  KVM/VMX: Add hv tlb range flush support

 arch/x86/hyperv/nested.c| 111 +++
 arch/x86/include/asm/hyperv-tlfs.h  |  17 +
 arch/x86/include/asm/kvm_host.h |  10 +++
 arch/x86/include/asm/mshyperv.h |   7 ++
 arch/x86/include/asm/trace/hyperv.h |  14 
 arch/x86/kvm/mmu.c  | 146 +++-
 arch/x86/kvm/paging_tmpl.h  |  16 +++-
 arch/x86/kvm/vmx.c  |  41 +++---
 8 files changed, 331 insertions(+), 31 deletions(-)

-- 
2.14.4
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 3/13] KVM: Replace old tlb flush function with new one to flush a specified range.

2018-09-10 Thread Tianyu Lan
This patch is to replace kvm_flush_remote_tlbs() with kvm_flush_
remote_tlbs_with_address() in some functions without logic change.

Signed-off-by: Lan Tianyu 
---
 arch/x86/kvm/mmu.c | 34 +++---
 arch/x86/kvm/paging_tmpl.h |  9 +++--
 2 files changed, 30 insertions(+), 13 deletions(-)

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 8cf47befc0f2..0ee310bad2c6 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -1482,8 +1482,12 @@ static bool __drop_large_spte(struct kvm *kvm, u64 
*sptep)
 
 static void drop_large_spte(struct kvm_vcpu *vcpu, u64 *sptep)
 {
-   if (__drop_large_spte(vcpu->kvm, sptep))
-   kvm_flush_remote_tlbs(vcpu->kvm);
+   if (__drop_large_spte(vcpu->kvm, sptep)) {
+   struct kvm_mmu_page *sp = page_header(__pa(sptep));
+
+   kvm_flush_remote_tlbs_with_address(vcpu->kvm, sp->gfn,
+   sp->gfn + KVM_PAGES_PER_HPAGE(sp->role.level) - 1);
+   }
 }
 
 /*
@@ -1770,7 +1774,7 @@ static int kvm_set_pte_rmapp(struct kvm *kvm, struct 
kvm_rmap_head *rmap_head,
}
 
if (need_flush)
-   kvm_flush_remote_tlbs(kvm);
+   kvm_flush_remote_tlbs_with_address(kvm, gfn, gfn);
 
return 0;
 }
@@ -1956,7 +1960,8 @@ static void rmap_recycle(struct kvm_vcpu *vcpu, u64 
*spte, gfn_t gfn)
rmap_head = gfn_to_rmap(vcpu->kvm, gfn, sp);
 
kvm_unmap_rmapp(vcpu->kvm, rmap_head, NULL, gfn, sp->role.level, 0);
-   kvm_flush_remote_tlbs(vcpu->kvm);
+   kvm_flush_remote_tlbs_with_address(vcpu->kvm, sp->gfn,
+   sp->gfn + KVM_PAGES_PER_HPAGE(sp->role.level) - 1);
 }
 
 int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end)
@@ -2472,7 +2477,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct 
kvm_vcpu *vcpu,
account_shadowed(vcpu->kvm, sp);
if (level == PT_PAGE_TABLE_LEVEL &&
  rmap_write_protect(vcpu, gfn))
-   kvm_flush_remote_tlbs(vcpu->kvm);
+   kvm_flush_remote_tlbs_with_address(vcpu->kvm, gfn, gfn);
 
if (level > PT_PAGE_TABLE_LEVEL && need_sync)
flush |= kvm_sync_pages(vcpu, gfn, _list);
@@ -2592,7 +2597,8 @@ static void validate_direct_spte(struct kvm_vcpu *vcpu, 
u64 *sptep,
return;
 
drop_parent_pte(child, sptep);
-   kvm_flush_remote_tlbs(vcpu->kvm);
+   kvm_flush_remote_tlbs_with_address(vcpu->kvm, child->gfn,
+   child->gfn);
}
 }
 
@@ -3016,8 +3022,10 @@ static int mmu_set_spte(struct kvm_vcpu *vcpu, u64 
*sptep, unsigned pte_access,
ret = RET_PF_EMULATE;
kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
}
+
if (set_spte_ret & SET_SPTE_NEED_REMOTE_TLB_FLUSH || flush)
-   kvm_flush_remote_tlbs(vcpu->kvm);
+   kvm_flush_remote_tlbs_with_address(vcpu->kvm, gfn,
+   gfn + KVM_PAGES_PER_HPAGE(level) - 1);
 
if (unlikely(is_mmio_spte(*sptep)))
ret = RET_PF_EMULATE;
@@ -5626,7 +5634,8 @@ void kvm_mmu_slot_remove_write_access(struct kvm *kvm,
 * on PT_WRITABLE_MASK anymore.
 */
if (flush)
-   kvm_flush_remote_tlbs(kvm);
+   kvm_flush_remote_tlbs_with_address(kvm, memslot->base_gfn,
+   memslot->base_gfn + memslot->npages - 1);
 }
 
 static bool kvm_mmu_zap_collapsible_spte(struct kvm *kvm,
@@ -5690,7 +5699,8 @@ void kvm_mmu_slot_leaf_clear_dirty(struct kvm *kvm,
 * dirty_bitmap.
 */
if (flush)
-   kvm_flush_remote_tlbs(kvm);
+   kvm_flush_remote_tlbs_with_address(kvm, memslot->base_gfn,
+   memslot->base_gfn + memslot->npages - 1);
 }
 EXPORT_SYMBOL_GPL(kvm_mmu_slot_leaf_clear_dirty);
 
@@ -5708,7 +5718,8 @@ void kvm_mmu_slot_largepage_remove_write_access(struct 
kvm *kvm,
lockdep_assert_held(>slots_lock);
 
if (flush)
-   kvm_flush_remote_tlbs(kvm);
+   kvm_flush_remote_tlbs_with_address(kvm, memslot->base_gfn,
+   memslot->base_gfn + memslot->npages - 1);
 }
 EXPORT_SYMBOL_GPL(kvm_mmu_slot_largepage_remove_write_access);
 
@@ -5725,7 +5736,8 @@ void kvm_mmu_slot_set_dirty(struct kvm *kvm,
 
/* see kvm_mmu_slot_leaf_clear_dirty */
if (flush)
-   kvm_flush_remote_tlbs(kvm);
+   kvm_flush_remote_tlbs_with_address(kvm, memslot->base_gfn,
+   memslot->base_gfn + memslot->npages - 1);
 }
 EXPORT_SYMBOL_GPL(kvm_mmu_slot_set_dirty);
 
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index 14ffd973df54..f45f1a5fbfe8 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -892,8 +892,13 @@ static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t 
gva, 

[PATCH 1/13] KVM: Add tlb_remote_flush_with_range callback in kvm_x86_ops

2018-09-10 Thread Tianyu Lan
Add flush range call back in the kvm_x86_ops and platform can use it
to register its associated function. The parameter "kvm_tlb_range"
accepts a single range and flush list which contains a list of ranges.

Signed-off-by: Lan Tianyu 
---
 arch/x86/include/asm/kvm_host.h | 8 
 1 file changed, 8 insertions(+)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index e12916e7c2fb..dcdf8cc16388 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -402,6 +402,12 @@ struct kvm_mmu {
u64 pdptrs[4]; /* pae */
 };
 
+struct kvm_tlb_range {
+   u64 start_gfn;
+   u64 end_gfn;
+   struct list_head *flush_list;
+};
+
 enum pmc_type {
KVM_PMC_GP = 0,
KVM_PMC_FIXED,
@@ -991,6 +997,8 @@ struct kvm_x86_ops {
 
void (*tlb_flush)(struct kvm_vcpu *vcpu, bool invalidate_gpa);
int  (*tlb_remote_flush)(struct kvm *kvm);
+   int  (*tlb_remote_flush_with_range)(struct kvm *kvm,
+   struct kvm_tlb_range *range);
 
/*
 * Flush any TLB entries associated with the given GVA.
-- 
2.14.4
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[ 1/1] KVM/MMU: Fix comment in walk_shadow_page_lockless_end()

2018-09-06 Thread Tianyu Lan
kvm_commit_zap_page() has been renamed to kvm_mmu_commit_zap_page()
This patch is to fix the commit.

Signed-off-by: Lan Tianyu 
---
 arch/x86/kvm/mmu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 7ccd29b95746..648b839a349d 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -947,7 +947,7 @@ static void walk_shadow_page_lockless_end(struct kvm_vcpu 
*vcpu)
 {
/*
 * Make sure the write to vcpu->mode is not reordered in front of
-* reads to sptes.  If it does, kvm_commit_zap_page() can see us
+* reads to sptes.  If it does, kvm_mmu_commit_zap_page() can see us
 * OUTSIDE_GUEST_MODE and proceed to free the shadow page table.
 */
smp_store_release(>mode, OUTSIDE_GUEST_MODE);
-- 
2.14.4
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH V3 0/4] KVM/x86/hyper-V: Introduce PV guest address space mapping flush support

2018-07-23 Thread Tianyu Lan
On 7/23/2018 3:39 PM, Wanpeng Li wrote:
> On Fri, 20 Jul 2018 at 16:32, Paolo Bonzini  wrote:
>>
>> On 20/07/2018 05:58, KY Srinivasan wrote:
>>>
>>>
>>>> -----Original Message-
>>>> From: Tianyu Lan
>>>> Sent: Thursday, July 19, 2018 1:40 AM
>>>> Cc: Tianyu Lan ; de...@linuxdriverproject.org;
>>>> Haiyang Zhang ; h...@zytor.com;
>>>> k...@vger.kernel.org; KY Srinivasan ; linux-
>>>> ker...@vger.kernel.org; mi...@redhat.com; pbonz...@redhat.com;
>>>> rkrc...@redhat.com; Stephen Hemminger ;
>>>> t...@linutronix.de; x...@kernel.org; Michael Kelley (EOSG)
>>>> ; vkuzn...@redhat.com
>>>> Subject: [PATCH V3 0/4] KVM/x86/hyper-V: Introduce PV guest address
>>>> space mapping flush support
>>>>
>>>> Hyper-V provides a para-virtualization hypercall
>>>> HvFlushGuestPhysicalAddressSpace
>>>> to flush nested VM address space mapping in l1 hypervisor and it's to 
>>>> reduce
>>>> overhead
>>>> of flushing ept tlb among vcpus. The tradition way is to send IPIs to all
>>>> affected
>>>> vcpus and executes INVEPT on each vcpus. It will trigger several vmexits 
>>>> for
>>>> IPI and
>>>> INVEPT emulation. The pv hypercall can help to flush specified ept table 
>>>> on all
>>>> vcpus
>>>> via one single hypercall.
>>>>
>>>> Change since v2:
>>>> - Make ept_pointers_match as tristate "check", "match" and 
>>>> "mismatch".
>>>> Set "check" in vmx_set_cr3(), check all ept table pointers in
>>>> hv_remote_flush_tlb()
>>>> and call hypercall when all ept pointers are same.
>>>> - Rename kvm_arch_hv_flush_remote_tlb with
>>>> kvm_arch_flush_remote_tlb and
>>>> Rename kvm_x86_ops->hv_tlb_remote_flush with kvm_x86_ops-
>>>>> tlb_remote_flush
>>>> - Fix issue that ignore updating tlbs_dirty during calling
>>>> kvm_arch_flush_remote_tlbs()
>>>> - Merge patch "KVM/VMX: Add identical ept table pointer check" and
>>>> patch "KVM/x86: Add tlb_remote_flush callback support for vmx"
>>>>
>>>> Change since v1:
>>>> - Fix compilation error for non-x86 platform.
>>>> - Use ept_pointers_match to check condition of identical ept
>>>>  table pointer and get ept pointer from struct 
>>>> vcpu_vmx->ept_pointer.
>>>> - Add hyperv_nested_flush_guest_mapping ftrace support
>>>>
>>>>
>>>>
>>>> Lan Tianyu (4):
>>>>X86/Hyper-V: Add flush HvFlushGuestPhysicalAddressSpace hypercall
>>>>  support
>>>>X86/Hyper-V: Add hyperv_nested_flush_guest_mapping ftrace support
>>>>KVM: Add tlb remote flush callback in kvm_x86_ops.
>>>>KVM/x86: Add tlb_remote_flush callback support for vmx
>>>>
>>>>   arch/x86/hyperv/Makefile|  2 +-
>>>>   arch/x86/hyperv/nested.c| 67
>>>> ++
>>>>   arch/x86/include/asm/hyperv-tlfs.h  |  8 +
>>>>   arch/x86/include/asm/kvm_host.h | 11 ++
>>>>   arch/x86/include/asm/mshyperv.h |  2 ++
>>>>   arch/x86/include/asm/trace/hyperv.h | 14 
>>>>   arch/x86/kvm/vmx.c  | 72
>>>> -
>>>>   include/linux/kvm_host.h|  7 
>>>>   virt/kvm/kvm_main.c |  3 +-
>>>>   9 files changed, 183 insertions(+), 3 deletions(-)
>>>>   create mode 100644 arch/x86/hyperv/nested.c
>>>
>>> Acked-by: K. Y. Srinivasan 
>>
>> Queued, thanks!
> 
> My CONFIG_HYPERV is disabled, there is a warning when compiling kvm/queue.
> warning: ‘hv_remote_flush_tlb’ defined but not used [-Wunused-function]
>   static int hv_remote_flush_tlb(struct kvm *kvm)

Thanks. Wanpeng! Just send a fix patch.

> 
> Regards,
> Wanpeng Li
> 
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[Update PATCH V3 1/4] X86/Hyper-V: Add flush HvFlushGuestPhysicalAddressSpace hypercall support

2018-07-19 Thread Tianyu Lan
Hyper-V supports a pv hypercall HvFlushGuestPhysicalAddressSpace to
flush nested VM address space mapping in l1 hypervisor and it's to
reduce overhead of flushing ept tlb among vcpus. This patch is to
implement it.

Signed-off-by: Lan Tianyu 
---
Change since v3
Remove GPL boilerplate.

 arch/x86/hyperv/Makefile   |  2 +-
 arch/x86/hyperv/nested.c   | 53 ++
 arch/x86/include/asm/hyperv-tlfs.h |  8 ++
 arch/x86/include/asm/mshyperv.h|  2 ++
 4 files changed, 64 insertions(+), 1 deletion(-)
 create mode 100644 arch/x86/hyperv/nested.c

diff --git a/arch/x86/hyperv/Makefile b/arch/x86/hyperv/Makefile
index b173d404e3df..b21ee65c4101 100644
--- a/arch/x86/hyperv/Makefile
+++ b/arch/x86/hyperv/Makefile
@@ -1,2 +1,2 @@
-obj-y  := hv_init.o mmu.o
+obj-y  := hv_init.o mmu.o nested.o
 obj-$(CONFIG_X86_64)   += hv_apic.o
diff --git a/arch/x86/hyperv/nested.c b/arch/x86/hyperv/nested.c
new file mode 100644
index ..3ad9d0fdea63
--- /dev/null
+++ b/arch/x86/hyperv/nested.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Hyper-V nested virtualization code.
+ *
+ * Copyright (C) 2018, Microsoft, Inc.
+ *
+ * Author : Lan Tianyu 
+ */
+
+
+#include 
+#include 
+#include 
+#include 
+
+int hyperv_flush_guest_mapping(u64 as)
+{
+   struct hv_guest_mapping_flush **flush_pcpu;
+   struct hv_guest_mapping_flush *flush;
+   u64 status;
+   unsigned long flags;
+   int ret = -EFAULT;
+
+   if (!hv_hypercall_pg)
+   goto fault;
+
+   local_irq_save(flags);
+
+   flush_pcpu = (struct hv_guest_mapping_flush **)
+   this_cpu_ptr(hyperv_pcpu_input_arg);
+
+   flush = *flush_pcpu;
+
+   if (unlikely(!flush)) {
+   local_irq_restore(flags);
+   goto fault;
+   }
+
+   flush->address_space = as;
+   flush->flags = 0;
+
+   status = hv_do_hypercall(HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE,
+flush, NULL);
+   local_irq_restore(flags);
+
+   if (!(status & HV_HYPERCALL_RESULT_MASK))
+   ret = 0;
+
+fault:
+   return ret;
+}
+EXPORT_SYMBOL_GPL(hyperv_flush_guest_mapping);
diff --git a/arch/x86/include/asm/hyperv-tlfs.h 
b/arch/x86/include/asm/hyperv-tlfs.h
index b8c89265baf0..08e24f552030 100644
--- a/arch/x86/include/asm/hyperv-tlfs.h
+++ b/arch/x86/include/asm/hyperv-tlfs.h
@@ -309,6 +309,7 @@ struct ms_hyperv_tsc_page {
 #define HV_X64_MSR_REENLIGHTENMENT_CONTROL 0x4106
 
 /* Nested features (CPUID 0x400A) EAX */
+#define HV_X64_NESTED_GUEST_MAPPING_FLUSH  BIT(18)
 #define HV_X64_NESTED_MSR_BITMAP   BIT(19)
 
 struct hv_reenlightenment_control {
@@ -350,6 +351,7 @@ struct hv_tsc_emulation_status {
 #define HVCALL_SEND_IPI_EX 0x0015
 #define HVCALL_POST_MESSAGE0x005c
 #define HVCALL_SIGNAL_EVENT0x005d
+#define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE 0x00af
 
 #define HV_X64_MSR_VP_ASSIST_PAGE_ENABLE   0x0001
 #define HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_SHIFT12
@@ -741,6 +743,12 @@ struct ipi_arg_ex {
struct hv_vpset vp_set;
 };
 
+/* HvFlushGuestPhysicalAddressSpace hypercalls */
+struct hv_guest_mapping_flush {
+   u64 address_space;
+   u64 flags;
+};
+
 /* HvFlushVirtualAddressSpace, HvFlushVirtualAddressList hypercalls */
 struct hv_tlb_flush {
u64 address_space;
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 3cd14311edfa..a6a615b49876 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -302,6 +302,7 @@ void hyperv_reenlightenment_intr(struct pt_regs *regs);
 void set_hv_tscchange_cb(void (*cb)(void));
 void clear_hv_tscchange_cb(void);
 void hyperv_stop_tsc_emulation(void);
+int hyperv_flush_guest_mapping(u64 as);
 
 #ifdef CONFIG_X86_64
 void hv_apic_init(void);
@@ -321,6 +322,7 @@ static inline struct hv_vp_assist_page 
*hv_get_vp_assist_page(unsigned int cpu)
 {
return NULL;
 }
+static inline int hyperv_flush_guest_mapping(u64 as) { return -1; }
 #endif /* CONFIG_HYPERV */
 
 #ifdef CONFIG_HYPERV_TSCPAGE
-- 
2.14.3
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH V3 1/4] X86/Hyper-V: Add flush HvFlushGuestPhysicalAddressSpace hypercall support

2018-07-19 Thread Tianyu Lan
On 7/19/2018 8:05 PM, Thomas Gleixner wrote:
> On Thu, 19 Jul 2018, Tianyu Lan wrote:
>> @@ -0,0 +1,64 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +
>> +/*
>> + * Hyper-V nested virtualization code.
>> + *
>> + * Copyright (C) 2018, Microsoft, Inc.
>> + *
>> + * Author : Lan Tianyu 
>> + *
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms of the GNU General Public License version 2 as published
>> + * by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful, but
>> + * WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
>> + * NON INFRINGEMENT.  See the GNU General Public License for more
>> + * details.
> 
> You already have the SPDX identifier. So the GPL boilerplate is not really
> required, unless your legal departement insist on it.
> 

Hi Thomas:
Thanks for your reminder. How about the following?


+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Hyper-V nested virtualization code.
+ *
+ * Copyright (C) 2018, Microsoft, Inc.
+ *
+ * Author : Lan Tianyu 
+ */

> Thanks,
> 
>   tglx
> 
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH V3 0/4] KVM/x86/hyper-V: Introduce PV guest address space mapping flush support

2018-07-19 Thread Tianyu Lan
On 7/19/2018 4:57 PM, Paolo Bonzini wrote:
> On 19/07/2018 10:39, Tianyu Lan wrote:
>> Hyper-V provides a para-virtualization hypercall 
>> HvFlushGuestPhysicalAddressSpace
>> to flush nested VM address space mapping in l1 hypervisor and it's to reduce 
>> overhead
>> of flushing ept tlb among vcpus. The tradition way is to send IPIs to all 
>> affected
>> vcpus and executes INVEPT on each vcpus. It will trigger several vmexits for 
>> IPI and
>> INVEPT emulation. The pv hypercall can help to flush specified ept table on 
>> all vcpus
>> via one single hypercall.
> 
> Thanks, this looks good apart from a global replace of EFAULT with
> ENOTSUP (which can be done when applying).  Can I have an explicit ack
> for patches 1 and 2 from the Hyper-V people?

Thanks, Paolo. I will try to hyper-V people's ack.

> 
> Thanks,
> 
> Paolo
> 
>> Change since v2:
>> - Make ept_pointers_match as tristate "check", "match" and 
>> "mismatch".
>> Set "check" in vmx_set_cr3(), check all ept table pointers in 
>> hv_remote_flush_tlb()
>> and call hypercall when all ept pointers are same.
>> - Rename kvm_arch_hv_flush_remote_tlb with kvm_arch_flush_remote_tlb 
>> and
>> Rename kvm_x86_ops->hv_tlb_remote_flush with 
>> kvm_x86_ops->tlb_remote_flush
>> - Fix issue that ignore updating tlbs_dirty during calling 
>> kvm_arch_flush_remote_tlbs()
>> - Merge patch "KVM/VMX: Add identical ept table pointer check" and
>> patch "KVM/x86: Add tlb_remote_flush callback support for vmx"
>>
>> Change since v1:
>> - Fix compilation error for non-x86 platform.
>> - Use ept_pointers_match to check condition of identical ept
>>  table pointer and get ept pointer from struct 
>> vcpu_vmx->ept_pointer.
>> - Add hyperv_nested_flush_guest_mapping ftrace support
>>  
>>
>>
>> Lan Tianyu (4):
>>X86/Hyper-V: Add flush HvFlushGuestPhysicalAddressSpace hypercall
>>  support
>>X86/Hyper-V: Add hyperv_nested_flush_guest_mapping ftrace support
>>KVM: Add tlb remote flush callback in kvm_x86_ops.
>>KVM/x86: Add tlb_remote_flush callback support for vmx
>>
>>   arch/x86/hyperv/Makefile|  2 +-
>>   arch/x86/hyperv/nested.c| 67 ++
>>   arch/x86/include/asm/hyperv-tlfs.h  |  8 +
>>   arch/x86/include/asm/kvm_host.h | 11 ++
>>   arch/x86/include/asm/mshyperv.h |  2 ++
>>   arch/x86/include/asm/trace/hyperv.h | 14 
>>   arch/x86/kvm/vmx.c  | 72 
>> -
>>   include/linux/kvm_host.h|  7 
>>   virt/kvm/kvm_main.c |  3 +-
>>   9 files changed, 183 insertions(+), 3 deletions(-)
>>   create mode 100644 arch/x86/hyperv/nested.c
>>
> 
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH V3 0/4] KVM/x86/hyper-V: Introduce PV guest address space mapping flush support

2018-07-19 Thread Tianyu Lan
Hyper-V provides a para-virtualization hypercall 
HvFlushGuestPhysicalAddressSpace
to flush nested VM address space mapping in l1 hypervisor and it's to reduce 
overhead
of flushing ept tlb among vcpus. The tradition way is to send IPIs to all 
affected
vcpus and executes INVEPT on each vcpus. It will trigger several vmexits for 
IPI and
INVEPT emulation. The pv hypercall can help to flush specified ept table on all 
vcpus
via one single hypercall.

Change since v2:
   - Make ept_pointers_match as tristate "check", "match" and "mismatch".
   Set "check" in vmx_set_cr3(), check all ept table pointers in 
hv_remote_flush_tlb()
   and call hypercall when all ept pointers are same.
   - Rename kvm_arch_hv_flush_remote_tlb with kvm_arch_flush_remote_tlb and
   Rename kvm_x86_ops->hv_tlb_remote_flush with 
kvm_x86_ops->tlb_remote_flush
   - Fix issue that ignore updating tlbs_dirty during calling 
kvm_arch_flush_remote_tlbs()
   - Merge patch "KVM/VMX: Add identical ept table pointer check" and
   patch "KVM/x86: Add tlb_remote_flush callback support for vmx"

Change since v1:
   - Fix compilation error for non-x86 platform.
   - Use ept_pointers_match to check condition of identical ept
table pointer and get ept pointer from struct vcpu_vmx->ept_pointer.
   - Add hyperv_nested_flush_guest_mapping ftrace support
 


Lan Tianyu (4):
  X86/Hyper-V: Add flush HvFlushGuestPhysicalAddressSpace hypercall
support
  X86/Hyper-V: Add hyperv_nested_flush_guest_mapping ftrace support
  KVM: Add tlb remote flush callback in kvm_x86_ops.
  KVM/x86: Add tlb_remote_flush callback support for vmx

 arch/x86/hyperv/Makefile|  2 +-
 arch/x86/hyperv/nested.c| 67 ++
 arch/x86/include/asm/hyperv-tlfs.h  |  8 +
 arch/x86/include/asm/kvm_host.h | 11 ++
 arch/x86/include/asm/mshyperv.h |  2 ++
 arch/x86/include/asm/trace/hyperv.h | 14 
 arch/x86/kvm/vmx.c  | 72 -
 include/linux/kvm_host.h|  7 
 virt/kvm/kvm_main.c |  3 +-
 9 files changed, 183 insertions(+), 3 deletions(-)
 create mode 100644 arch/x86/hyperv/nested.c

-- 
2.14.3
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH V3 2/4] X86/Hyper-V: Add hyperv_nested_flush_guest_mapping ftrace support

2018-07-19 Thread Tianyu Lan
This patch is to add hyperv_nested_flush_guest_mapping support to trace
hvFlushGuestPhysicalAddressSpace hypercall.

Signed-off-by: Lan Tianyu 
---
 arch/x86/hyperv/nested.c|  3 +++
 arch/x86/include/asm/trace/hyperv.h | 14 ++
 2 files changed, 17 insertions(+)

diff --git a/arch/x86/hyperv/nested.c b/arch/x86/hyperv/nested.c
index 74dd38b5221d..42a3232f2835 100644
--- a/arch/x86/hyperv/nested.c
+++ b/arch/x86/hyperv/nested.c
@@ -25,6 +25,8 @@
 #include 
 #include 
 
+#include 
+
 int hyperv_flush_guest_mapping(u64 as)
 {
struct hv_guest_mapping_flush **flush_pcpu;
@@ -59,6 +61,7 @@ int hyperv_flush_guest_mapping(u64 as)
ret = 0;
 
 fault:
+   trace_hyperv_nested_flush_guest_mapping(as, ret);
return ret;
 }
 EXPORT_SYMBOL_GPL(hyperv_flush_guest_mapping);
diff --git a/arch/x86/include/asm/trace/hyperv.h 
b/arch/x86/include/asm/trace/hyperv.h
index 4253bca99989..e1ffe61de8d6 100644
--- a/arch/x86/include/asm/trace/hyperv.h
+++ b/arch/x86/include/asm/trace/hyperv.h
@@ -28,6 +28,20 @@ TRACE_EVENT(hyperv_mmu_flush_tlb_others,
  __entry->addr, __entry->end)
);
 
+TRACE_EVENT(hyperv_nested_flush_guest_mapping,
+   TP_PROTO(u64 as, int ret),
+   TP_ARGS(as, ret),
+
+   TP_STRUCT__entry(
+   __field(u64, as)
+   __field(int, ret)
+   ),
+   TP_fast_assign(__entry->as = as;
+  __entry->ret = ret;
+   ),
+   TP_printk("address space %llx ret %d", __entry->as, __entry->ret)
+   );
+
 #endif /* CONFIG_HYPERV */
 
 #undef TRACE_INCLUDE_PATH
-- 
2.14.3
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH V3 1/4] X86/Hyper-V: Add flush HvFlushGuestPhysicalAddressSpace hypercall support

2018-07-19 Thread Tianyu Lan
Hyper-V supports a pv hypercall HvFlushGuestPhysicalAddressSpace to
flush nested VM address space mapping in l1 hypervisor and it's to
reduce overhead of flushing ept tlb among vcpus. This patch is to
implement it.

Signed-off-by: Lan Tianyu 
---
 arch/x86/hyperv/Makefile   |  2 +-
 arch/x86/hyperv/nested.c   | 64 ++
 arch/x86/include/asm/hyperv-tlfs.h |  8 +
 arch/x86/include/asm/mshyperv.h|  2 ++
 4 files changed, 75 insertions(+), 1 deletion(-)
 create mode 100644 arch/x86/hyperv/nested.c

diff --git a/arch/x86/hyperv/Makefile b/arch/x86/hyperv/Makefile
index b173d404e3df..b21ee65c4101 100644
--- a/arch/x86/hyperv/Makefile
+++ b/arch/x86/hyperv/Makefile
@@ -1,2 +1,2 @@
-obj-y  := hv_init.o mmu.o
+obj-y  := hv_init.o mmu.o nested.o
 obj-$(CONFIG_X86_64)   += hv_apic.o
diff --git a/arch/x86/hyperv/nested.c b/arch/x86/hyperv/nested.c
new file mode 100644
index ..74dd38b5221d
--- /dev/null
+++ b/arch/x86/hyperv/nested.c
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Hyper-V nested virtualization code.
+ *
+ * Copyright (C) 2018, Microsoft, Inc.
+ *
+ * Author : Lan Tianyu 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ */
+
+
+#include 
+#include 
+#include 
+#include 
+
+int hyperv_flush_guest_mapping(u64 as)
+{
+   struct hv_guest_mapping_flush **flush_pcpu;
+   struct hv_guest_mapping_flush *flush;
+   u64 status;
+   unsigned long flags;
+   int ret = -EFAULT;
+
+   if (!hv_hypercall_pg)
+   goto fault;
+
+   local_irq_save(flags);
+
+   flush_pcpu = (struct hv_guest_mapping_flush **)
+   this_cpu_ptr(hyperv_pcpu_input_arg);
+
+   flush = *flush_pcpu;
+
+   if (unlikely(!flush)) {
+   local_irq_restore(flags);
+   goto fault;
+   }
+
+   flush->address_space = as;
+   flush->flags = 0;
+
+   status = hv_do_hypercall(HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE,
+flush, NULL);
+   local_irq_restore(flags);
+
+   if (!(status & HV_HYPERCALL_RESULT_MASK))
+   ret = 0;
+
+fault:
+   return ret;
+}
+EXPORT_SYMBOL_GPL(hyperv_flush_guest_mapping);
diff --git a/arch/x86/include/asm/hyperv-tlfs.h 
b/arch/x86/include/asm/hyperv-tlfs.h
index b8c89265baf0..08e24f552030 100644
--- a/arch/x86/include/asm/hyperv-tlfs.h
+++ b/arch/x86/include/asm/hyperv-tlfs.h
@@ -309,6 +309,7 @@ struct ms_hyperv_tsc_page {
 #define HV_X64_MSR_REENLIGHTENMENT_CONTROL 0x4106
 
 /* Nested features (CPUID 0x400A) EAX */
+#define HV_X64_NESTED_GUEST_MAPPING_FLUSH  BIT(18)
 #define HV_X64_NESTED_MSR_BITMAP   BIT(19)
 
 struct hv_reenlightenment_control {
@@ -350,6 +351,7 @@ struct hv_tsc_emulation_status {
 #define HVCALL_SEND_IPI_EX 0x0015
 #define HVCALL_POST_MESSAGE0x005c
 #define HVCALL_SIGNAL_EVENT0x005d
+#define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE 0x00af
 
 #define HV_X64_MSR_VP_ASSIST_PAGE_ENABLE   0x0001
 #define HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_SHIFT12
@@ -741,6 +743,12 @@ struct ipi_arg_ex {
struct hv_vpset vp_set;
 };
 
+/* HvFlushGuestPhysicalAddressSpace hypercalls */
+struct hv_guest_mapping_flush {
+   u64 address_space;
+   u64 flags;
+};
+
 /* HvFlushVirtualAddressSpace, HvFlushVirtualAddressList hypercalls */
 struct hv_tlb_flush {
u64 address_space;
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 3cd14311edfa..a6a615b49876 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -302,6 +302,7 @@ void hyperv_reenlightenment_intr(struct pt_regs *regs);
 void set_hv_tscchange_cb(void (*cb)(void));
 void clear_hv_tscchange_cb(void);
 void hyperv_stop_tsc_emulation(void);
+int hyperv_flush_guest_mapping(u64 as);
 
 #ifdef CONFIG_X86_64
 void hv_apic_init(void);
@@ -321,6 +322,7 @@ static inline struct hv_vp_assist_page 
*hv_get_vp_assist_page(unsigned int cpu)
 {
return NULL;
 }
+static inline int hyperv_flush_guest_mapping(u64 as) { return -1; }
 #endif /* CONFIG_HYPERV */
 
 #ifdef CONFIG_HYPERV_TSCPAGE
-- 
2.14.3
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH V2 2/5] KVM: Add tlb remote flush callback in kvm_x86_ops.

2018-07-18 Thread Tianyu Lan
Hi Paolo:
Thanks for review.

On 7/18/2018 8:01 PM, Paolo Bonzini wrote:
> On 09/07/2018 11:02, Tianyu Lan wrote:
>> +/*
>> + * Call kvm_arch_hv_tlb_remote first and go back old way when
>> + * return failure.
>> + */
>> +if (!kvm_arch_hv_flush_remote_tlb(kvm))
>> +return;
>> +
>>  /*
>>   * Read tlbs_dirty before setting KVM_REQ_TLB_FLUSH in
>>   * kvm_make_all_cpus_request.
>>   */
>> -long dirty_count = smp_load_acquire(>tlbs_dirty);
>> +dirty_count = smp_load_acquire(>tlbs_dirty);
> 
> Also, the call to kvm_arch_flush_remote_tlbs should not replace the
> whole function.  It should be something like:
> 
>  long dirty_count = smp_load_acquire(>tlbs_dirty);
> 
>  /*
>   * We want to publish modifications to the page tables before reading
>   * mode. Pairs with a memory barrier in arch-specific code.
>   * - x86: smp_mb__after_srcu_read_unlock in vcpu_enter_guest
>   * and smp_mb in walk_shadow_page_lockless_begin/end.
>   * - powerpc: smp_mb in kvmppc_prepare_to_enter.
>   *
>   * There is already an smp_mb__after_atomic() before
>   * kvm_make_all_cpus_request() reads vcpu->mode. We reuse that
>   * barrier here.
>   */
>  if (!kvm_arch_hv_flush_remote_tlb(kvm) ||
>   kvm_make_all_cpus_request(kvm, KVM_REQ_TLB_FLUSH))
>  ++kvm->stat.remote_tlb_flush;
>  cmpxchg(>tlbs_dirty, dirty_count, 0);
> 
> Otherwise, kvm_mmu_notifier_invalidate_range_start will incorrectly skip
> a TLB flush.

Nice catch. Will update in the next version.

> 
> Thanks,
> 
> Paolo
> 
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH V2 3/5] KVM/VMX: Add identical ept table pointer check

2018-07-18 Thread Tianyu Lan
On 7/18/2018 7:59 PM, Paolo Bonzini wrote:
> On 09/07/2018 11:02, Tianyu Lan wrote:
>> +static void check_ept_pointer(struct kvm_vcpu *vcpu, u64 eptp)
>> +{
>> +struct kvm *kvm = vcpu->kvm;
>> +u64 tmp_eptp = INVALID_PAGE;
>> +int i;
>> +
>> +if (!kvm_x86_ops->tlb_remote_flush)
>> +return;
>> +
>> +spin_lock(_kvm_vmx(kvm)->ept_pointer_lock);
>> +to_vmx(vcpu)->ept_pointer = eptp;
>> +
>> +kvm_for_each_vcpu(i, vcpu, kvm) {
>> +if (!VALID_PAGE(tmp_eptp)) {
>> +tmp_eptp = to_vmx(vcpu)->ept_pointer;
>> +} else if (tmp_eptp != to_vmx(vcpu)->ept_pointer) {
>> +to_kvm_vmx(kvm)->ept_pointers_match = false;
>> +spin_unlock(_kvm_vmx(kvm)->ept_pointer_lock);
>> +return;
>> +}
>> +}
>> +
>> +to_kvm_vmx(kvm)->ept_pointers_match = true;
>> +spin_unlock(_kvm_vmx(kvm)->ept_pointer_lock);
>> +}
>> +
> 
> Is there any reason to do the check here, rather than the first time the
> TLB flush is invoked?  You could:
> 
> - have a tristate (true, false, check) value for ept_pointers_match
> 
> - reset it to "check" in vmx_set_cr3
> 
> - set it to either true or false in tlb_remote_flush if it is check, and
> do the hypercall if it is true.
> 

Thanks for your suggestion. Will update.

> Paolo
> 
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH V2 1/5] X86/Hyper-V: Add flush HvFlushGuestPhysicalAddressSpace hypercall support

2018-07-11 Thread Tianyu Lan
Hi Michael:
Thanks for your review.

On 7/11/2018 5:29 AM, Michael Kelley (EOSG) wrote:
> From: Tianyu Lan  Monday, July 9, 2018 2:03 AM
>> Hyper-V supports a pv hypercall HvFlushGuestPhysicalAddressSpace to
>> flush nested VM address space mapping in l1 hypervisor and it's to
>> reduce overhead of flushing ept tlb among vcpus. This patch is to
>> implement it.
>>
>> Signed-off-by: Lan Tianyu 
>> ---
>>   arch/x86/hyperv/Makefile   |  2 +-
>>   arch/x86/hyperv/nested.c   | 64 
>> ++
>>   arch/x86/include/asm/hyperv-tlfs.h |  8 +
>>   arch/x86/include/asm/mshyperv.h|  2 ++
>>   4 files changed, 75 insertions(+), 1 deletion(-)
>>   create mode 100644 arch/x86/hyperv/nested.c
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +
>> +int hyperv_flush_guest_mapping(u64 as)
>> +{
>> +struct hv_guest_mapping_flush **flush_pcpu;
>> +struct hv_guest_mapping_flush *flush;
>> +u64 status;
>> +unsigned long flags;
>> +int ret = -EFAULT;
>> +
>> +if (!hv_hypercall_pg)
>> +goto fault;
>> +
>> +local_irq_save(flags);
>> +
>> +flush_pcpu = (struct hv_guest_mapping_flush **)
>> +this_cpu_ptr(hyperv_pcpu_input_arg);
>> +
>> +flush = *flush_pcpu;
>> +
>> +if (unlikely(!flush)) {
>> +local_irq_restore(flags);
>> +goto fault;
>> +}
>> +
>> +flush->address_space = as;
>> +flush->flags = 0;
>> +
>> +status = hv_do_hypercall(HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE,
>> + flush, NULL);
> 
> Did you consider using a "fast" hypercall?  Unless there's some reason I'm
> not aware of, a "fast" hypercall would be perfect here as there are 16 bytes
> of input and no output. Vitaly recently added hv_do_fast_hypercall16()
> in the linux-next tree. See __send_ipi_mask() in hv_apic.c in linux-next
> for an example of usage.  With a fast hypercall, you don't need the code for
> getting the per-cpu input arg or the code for local irq save/restore, so the
> code that is left is a lot faster and simpler.
> 
> Michael
> 

Good suggestion. But the "fast" hypercall still is not available in 
kvm-next branch and it's in the x86 tip repo. We may rework this with 
"fast" hypercall in the next kernel development cycle if this patchset 
is accepted in for 4.19.

>> +local_irq_restore(flags);
>> +
>> +if (!(status & HV_HYPERCALL_RESULT_MASK))
>> +ret = 0;
>> +
>> +fault:
>> +return ret;
>> +}
>> +EXPORT_SYMBOL_GPL(hyperv_flush_guest_mapping);
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH V2 2/5] KVM: Add tlb remote flush callback in kvm_x86_ops.

2018-07-09 Thread Tianyu Lan
This patch is to provide a way for platforms to register hv tlb remote
flush callback and this helps to optimize operation of tlb flush
among vcpus for nested virtualization case.

Signed-off-by: Lan Tianyu 
---
Change since v1:
   Add kvm_arch_hv_flush_remote_tlb() to avoid compilation issue
for non-x86 platform.
---
 arch/x86/include/asm/kvm_host.h | 11 +++
 include/linux/kvm_host.h|  7 +++
 virt/kvm/kvm_main.c | 11 ++-
 3 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index c13cd28d9d1b..d89e4204816c 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -973,6 +973,7 @@ struct kvm_x86_ops {
void (*set_rflags)(struct kvm_vcpu *vcpu, unsigned long rflags);
 
void (*tlb_flush)(struct kvm_vcpu *vcpu, bool invalidate_gpa);
+   int  (*hv_tlb_remote_flush)(struct kvm *kvm);
 
void (*run)(struct kvm_vcpu *vcpu);
int (*handle_exit)(struct kvm_vcpu *vcpu);
@@ -1117,6 +1118,16 @@ static inline void kvm_arch_free_vm(struct kvm *kvm)
return kvm_x86_ops->vm_free(kvm);
 }
 
+#define __KVM_HAVE_HV_FLUSH_REMOTE_TLB
+static inline int kvm_arch_hv_flush_remote_tlb(struct kvm *kvm)
+{
+   if (kvm_x86_ops->hv_tlb_remote_flush &&
+   !kvm_x86_ops->hv_tlb_remote_flush(kvm))
+   return 0;
+   else
+   return -EFAULT;
+}
+
 int kvm_mmu_module_init(void);
 void kvm_mmu_module_exit(void);
 
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 4ee7bc548a83..0c2c36cb041b 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -827,6 +827,13 @@ static inline void kvm_arch_free_vm(struct kvm *kvm)
 }
 #endif
 
+#ifndef __KVM_HAVE_HV_FLUSH_REMOTE_TLB
+static inline int kvm_arch_hv_flush_remote_tlb(struct kvm *kvm)
+{
+   return -EFAULT;
+}
+#endif
+
 #ifdef __KVM_HAVE_ARCH_NONCOHERENT_DMA
 void kvm_arch_register_noncoherent_dma(struct kvm *kvm);
 void kvm_arch_unregister_noncoherent_dma(struct kvm *kvm);
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 8b47507faab5..c2b5e3273848 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -256,11 +256,20 @@ bool kvm_make_all_cpus_request(struct kvm *kvm, unsigned 
int req)
 #ifndef CONFIG_HAVE_KVM_ARCH_TLB_FLUSH_ALL
 void kvm_flush_remote_tlbs(struct kvm *kvm)
 {
+   long dirty_count;
+
+   /*
+* Call kvm_arch_hv_tlb_remote first and go back old way when
+* return failure.
+*/
+   if (!kvm_arch_hv_flush_remote_tlb(kvm))
+   return;
+
/*
 * Read tlbs_dirty before setting KVM_REQ_TLB_FLUSH in
 * kvm_make_all_cpus_request.
 */
-   long dirty_count = smp_load_acquire(>tlbs_dirty);
+   dirty_count = smp_load_acquire(>tlbs_dirty);
 
/*
 * We want to publish modifications to the page tables before reading
-- 
2.14.3
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH V2 1/5] X86/Hyper-V: Add flush HvFlushGuestPhysicalAddressSpace hypercall support

2018-07-09 Thread Tianyu Lan
Hyper-V supports a pv hypercall HvFlushGuestPhysicalAddressSpace to
flush nested VM address space mapping in l1 hypervisor and it's to
reduce overhead of flushing ept tlb among vcpus. This patch is to
implement it.

Signed-off-by: Lan Tianyu 
---
 arch/x86/hyperv/Makefile   |  2 +-
 arch/x86/hyperv/nested.c   | 64 ++
 arch/x86/include/asm/hyperv-tlfs.h |  8 +
 arch/x86/include/asm/mshyperv.h|  2 ++
 4 files changed, 75 insertions(+), 1 deletion(-)
 create mode 100644 arch/x86/hyperv/nested.c

diff --git a/arch/x86/hyperv/Makefile b/arch/x86/hyperv/Makefile
index b173d404e3df..b21ee65c4101 100644
--- a/arch/x86/hyperv/Makefile
+++ b/arch/x86/hyperv/Makefile
@@ -1,2 +1,2 @@
-obj-y  := hv_init.o mmu.o
+obj-y  := hv_init.o mmu.o nested.o
 obj-$(CONFIG_X86_64)   += hv_apic.o
diff --git a/arch/x86/hyperv/nested.c b/arch/x86/hyperv/nested.c
new file mode 100644
index ..74dd38b5221d
--- /dev/null
+++ b/arch/x86/hyperv/nested.c
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Hyper-V nested virtualization code.
+ *
+ * Copyright (C) 2018, Microsoft, Inc.
+ *
+ * Author : Lan Tianyu 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ */
+
+
+#include 
+#include 
+#include 
+#include 
+
+int hyperv_flush_guest_mapping(u64 as)
+{
+   struct hv_guest_mapping_flush **flush_pcpu;
+   struct hv_guest_mapping_flush *flush;
+   u64 status;
+   unsigned long flags;
+   int ret = -EFAULT;
+
+   if (!hv_hypercall_pg)
+   goto fault;
+
+   local_irq_save(flags);
+
+   flush_pcpu = (struct hv_guest_mapping_flush **)
+   this_cpu_ptr(hyperv_pcpu_input_arg);
+
+   flush = *flush_pcpu;
+
+   if (unlikely(!flush)) {
+   local_irq_restore(flags);
+   goto fault;
+   }
+
+   flush->address_space = as;
+   flush->flags = 0;
+
+   status = hv_do_hypercall(HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE,
+flush, NULL);
+   local_irq_restore(flags);
+
+   if (!(status & HV_HYPERCALL_RESULT_MASK))
+   ret = 0;
+
+fault:
+   return ret;
+}
+EXPORT_SYMBOL_GPL(hyperv_flush_guest_mapping);
diff --git a/arch/x86/include/asm/hyperv-tlfs.h 
b/arch/x86/include/asm/hyperv-tlfs.h
index b8c89265baf0..08e24f552030 100644
--- a/arch/x86/include/asm/hyperv-tlfs.h
+++ b/arch/x86/include/asm/hyperv-tlfs.h
@@ -309,6 +309,7 @@ struct ms_hyperv_tsc_page {
 #define HV_X64_MSR_REENLIGHTENMENT_CONTROL 0x4106
 
 /* Nested features (CPUID 0x400A) EAX */
+#define HV_X64_NESTED_GUEST_MAPPING_FLUSH  BIT(18)
 #define HV_X64_NESTED_MSR_BITMAP   BIT(19)
 
 struct hv_reenlightenment_control {
@@ -350,6 +351,7 @@ struct hv_tsc_emulation_status {
 #define HVCALL_SEND_IPI_EX 0x0015
 #define HVCALL_POST_MESSAGE0x005c
 #define HVCALL_SIGNAL_EVENT0x005d
+#define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE 0x00af
 
 #define HV_X64_MSR_VP_ASSIST_PAGE_ENABLE   0x0001
 #define HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_SHIFT12
@@ -741,6 +743,12 @@ struct ipi_arg_ex {
struct hv_vpset vp_set;
 };
 
+/* HvFlushGuestPhysicalAddressSpace hypercalls */
+struct hv_guest_mapping_flush {
+   u64 address_space;
+   u64 flags;
+};
+
 /* HvFlushVirtualAddressSpace, HvFlushVirtualAddressList hypercalls */
 struct hv_tlb_flush {
u64 address_space;
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 3cd14311edfa..a6a615b49876 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -302,6 +302,7 @@ void hyperv_reenlightenment_intr(struct pt_regs *regs);
 void set_hv_tscchange_cb(void (*cb)(void));
 void clear_hv_tscchange_cb(void);
 void hyperv_stop_tsc_emulation(void);
+int hyperv_flush_guest_mapping(u64 as);
 
 #ifdef CONFIG_X86_64
 void hv_apic_init(void);
@@ -321,6 +322,7 @@ static inline struct hv_vp_assist_page 
*hv_get_vp_assist_page(unsigned int cpu)
 {
return NULL;
 }
+static inline int hyperv_flush_guest_mapping(u64 as) { return -1; }
 #endif /* CONFIG_HYPERV */
 
 #ifdef CONFIG_HYPERV_TSCPAGE
-- 
2.14.3
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH V2 3/5] KVM/VMX: Add identical ept table pointer check

2018-07-09 Thread Tianyu Lan
This patch is to check ept table pointer of each cpus when set ept
tables and store identical ept table pointer if all ept table pointers
of single VM are same. This is for support of para-virt ept flush
hypercall.

Signed-off-by: Lan Tianyu 
---
Change since v1:
   Replace identical_ept_pointer with ept_pointers_match and
check kvm_x86_ops->tlb_remote_flush in check_ept_pointer().
---
 arch/x86/kvm/vmx.c | 34 ++
 1 file changed, 34 insertions(+)

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 1689f433f3a0..8142b2da430a 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -194,6 +194,9 @@ struct kvm_vmx {
unsigned int tss_addr;
bool ept_identity_pagetable_done;
gpa_t ept_identity_map_addr;
+
+   bool ept_pointers_match;
+   spinlock_t ept_pointer_lock;
 };
 
 #define NR_AUTOLOAD_MSRS 8
@@ -853,6 +856,7 @@ struct vcpu_vmx {
 */
u64 msr_ia32_feature_control;
u64 msr_ia32_feature_control_valid_bits;
+   u64 ept_pointer;
 };
 
 enum segment_cache_field {
@@ -4958,6 +4962,32 @@ static u64 construct_eptp(struct kvm_vcpu *vcpu, 
unsigned long root_hpa)
return eptp;
 }
 
+static void check_ept_pointer(struct kvm_vcpu *vcpu, u64 eptp)
+{
+   struct kvm *kvm = vcpu->kvm;
+   u64 tmp_eptp = INVALID_PAGE;
+   int i;
+
+   if (!kvm_x86_ops->tlb_remote_flush)
+   return;
+
+   spin_lock(_kvm_vmx(kvm)->ept_pointer_lock);
+   to_vmx(vcpu)->ept_pointer = eptp;
+
+   kvm_for_each_vcpu(i, vcpu, kvm) {
+   if (!VALID_PAGE(tmp_eptp)) {
+   tmp_eptp = to_vmx(vcpu)->ept_pointer;
+   } else if (tmp_eptp != to_vmx(vcpu)->ept_pointer) {
+   to_kvm_vmx(kvm)->ept_pointers_match = false;
+   spin_unlock(_kvm_vmx(kvm)->ept_pointer_lock);
+   return;
+   }
+   }
+
+   to_kvm_vmx(kvm)->ept_pointers_match = true;
+   spin_unlock(_kvm_vmx(kvm)->ept_pointer_lock);
+}
+
 static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
 {
unsigned long guest_cr3;
@@ -4967,6 +4997,8 @@ static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned 
long cr3)
if (enable_ept) {
eptp = construct_eptp(vcpu, cr3);
vmcs_write64(EPT_POINTER, eptp);
+   check_ept_pointer(vcpu, eptp);
+
if (enable_unrestricted_guest || is_paging(vcpu) ||
is_guest_mode(vcpu))
guest_cr3 = kvm_read_cr3(vcpu);
@@ -10383,6 +10415,8 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm 
*kvm, unsigned int id)
 
 static int vmx_vm_init(struct kvm *kvm)
 {
+   spin_lock_init(_kvm_vmx(kvm)->ept_pointer_lock);
+
if (!ple_gap)
kvm->arch.pause_in_guest = true;
return 0;
-- 
2.14.3
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH V2 5/5] X86/Hyper-V: Add hyperv_nested_flush_guest_mapping ftrace support

2018-07-09 Thread Tianyu Lan
This patch is to add hyperv_nested_flush_guest_mapping support to trace
hvFlushGuestPhysicalAddressSpace hypercall.

Signed-off-by: Lan Tianyu 
---
 arch/x86/hyperv/nested.c|  3 +++
 arch/x86/include/asm/trace/hyperv.h | 14 ++
 2 files changed, 17 insertions(+)

diff --git a/arch/x86/hyperv/nested.c b/arch/x86/hyperv/nested.c
index 74dd38b5221d..42a3232f2835 100644
--- a/arch/x86/hyperv/nested.c
+++ b/arch/x86/hyperv/nested.c
@@ -25,6 +25,8 @@
 #include 
 #include 
 
+#include 
+
 int hyperv_flush_guest_mapping(u64 as)
 {
struct hv_guest_mapping_flush **flush_pcpu;
@@ -59,6 +61,7 @@ int hyperv_flush_guest_mapping(u64 as)
ret = 0;
 
 fault:
+   trace_hyperv_nested_flush_guest_mapping(as, ret);
return ret;
 }
 EXPORT_SYMBOL_GPL(hyperv_flush_guest_mapping);
diff --git a/arch/x86/include/asm/trace/hyperv.h 
b/arch/x86/include/asm/trace/hyperv.h
index 4253bca99989..e1ffe61de8d6 100644
--- a/arch/x86/include/asm/trace/hyperv.h
+++ b/arch/x86/include/asm/trace/hyperv.h
@@ -28,6 +28,20 @@ TRACE_EVENT(hyperv_mmu_flush_tlb_others,
  __entry->addr, __entry->end)
);
 
+TRACE_EVENT(hyperv_nested_flush_guest_mapping,
+   TP_PROTO(u64 as, int ret),
+   TP_ARGS(as, ret),
+
+   TP_STRUCT__entry(
+   __field(u64, as)
+   __field(int, ret)
+   ),
+   TP_fast_assign(__entry->as = as;
+  __entry->ret = ret;
+   ),
+   TP_printk("address space %llx ret %d", __entry->as, __entry->ret)
+   );
+
 #endif /* CONFIG_HYPERV */
 
 #undef TRACE_INCLUDE_PATH
-- 
2.14.3
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH V2 4/5] KVM/x86: Add tlb_remote_flush callback support for vmx

2018-07-09 Thread Tianyu Lan
Register tlb_remote_flush callback for vmx when hyperv capability of
nested guest mapping flush is detected. The interface can help to
reduce overhead when flush ept table among vcpus for nested VM. The
tradition way is to send IPIs to all affected vcpus and executes
INVEPT on each vcpus. It will trigger several vmexits for IPI
and INVEPT emulation. Hyper-V provides such hypercall to do
flush for all vcpus.

Signed-off-by: Lan Tianyu 
---
Change since v1:
   Use ept_pointers_match to check condition of identical ept
table pointer and get ept pointer from struct vcpu_vmx->ept_pointer.
---
 arch/x86/kvm/vmx.c | 27 ++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 8142b2da430a..55fe14d1d4d4 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -4778,6 +4778,25 @@ static inline void __vmx_flush_tlb(struct kvm_vcpu 
*vcpu, int vpid,
}
 }
 
+static int hv_remote_flush_tlb(struct kvm *kvm)
+{
+   int ret;
+
+   spin_lock(_kvm_vmx(kvm)->ept_pointer_lock);
+
+   if (!to_kvm_vmx(kvm)->ept_pointers_match) {
+   ret = -EFAULT;
+   goto out;
+   }
+
+   ret = hyperv_flush_guest_mapping(
+   to_vmx(kvm_get_vcpu(kvm, 0))->ept_pointer);
+
+out:
+   spin_unlock(_kvm_vmx(kvm)->ept_pointer_lock);
+   return ret;
+}
+
 static void vmx_flush_tlb(struct kvm_vcpu *vcpu, bool invalidate_gpa)
 {
__vmx_flush_tlb(vcpu, to_vmx(vcpu)->vpid, invalidate_gpa);
@@ -4968,7 +4987,7 @@ static void check_ept_pointer(struct kvm_vcpu *vcpu, u64 
eptp)
u64 tmp_eptp = INVALID_PAGE;
int i;
 
-   if (!kvm_x86_ops->tlb_remote_flush)
+   if (!kvm_x86_ops->hv_tlb_remote_flush)
return;
 
spin_lock(_kvm_vmx(kvm)->ept_pointer_lock);
@@ -7570,6 +7589,12 @@ static __init int hardware_setup(void)
if (enable_ept && !cpu_has_vmx_ept_2m_page())
kvm_disable_largepages();
 
+#if IS_ENABLED(CONFIG_HYPERV)
+   if (ms_hyperv.nested_features & HV_X64_NESTED_GUEST_MAPPING_FLUSH
+   && enable_ept)
+   kvm_x86_ops->hv_tlb_remote_flush = hv_remote_flush_tlb;
+#endif
+
if (!cpu_has_vmx_ple()) {
ple_gap = 0;
ple_window = 0;
-- 
2.14.3
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH V2 0/5] KVM/x86/hyper-V: Introduce PV guest address space mapping flush support

2018-07-09 Thread Tianyu Lan
Hyper-V provides a para-virtualization hypercall 
HvFlushGuestPhysicalAddressSpace
to flush nested VM address space mapping in l1 hypervisor and it's to reduce 
overhead
of flushing ept tlb among vcpus. The tradition way is to send IPIs to all 
affected
vcpus and executes INVEPT on each vcpus. It will trigger several vmexits for 
IPI and
INVEPT emulation. The pv hypercall can help to flush specified ept table on all 
vcpus
via one single hypercall.

Change since v1:
   - Fix compilation error for non-x86 platform.
   - Use ept_pointers_match to check condition of identical ept
table pointer and get ept pointer from struct vcpu_vmx->ept_pointer.
   - Add hyperv_nested_flush_guest_mapping ftrace support

Lan Tianyu (5):
  X86/Hyper-V: Add flush HvFlushGuestPhysicalAddressSpace hypercall
support
  KVM: Add tlb remote flush callback in kvm_x86_ops.
  KVM/VMX: Add identical ept table pointer check
  KVM/x86: Add tlb_remote_flush callback support for vmx
  X86/Hyper-V: Add hyperv_nested_flush_guest_mapping ftrace support

 arch/x86/hyperv/Makefile|  2 +-
 arch/x86/hyperv/nested.c| 67 +
 arch/x86/include/asm/hyperv-tlfs.h  |  8 +
 arch/x86/include/asm/kvm_host.h | 11 ++
 arch/x86/include/asm/mshyperv.h |  2 ++
 arch/x86/include/asm/trace/hyperv.h | 14 
 arch/x86/kvm/vmx.c  | 59 
 include/linux/kvm_host.h|  7 
 virt/kvm/kvm_main.c | 11 +-
 9 files changed, 179 insertions(+), 2 deletions(-)
 create mode 100644 arch/x86/hyperv/nested.c

-- 
2.14.3
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 1/4] X86/Hyper-V: Add flush HvFlushGuestPhysicalAddressSpace hypercall support

2018-07-02 Thread Tianyu Lan
Hyper-V supports a pv hypercall HvFlushGuestPhysicalAddressSpace to
flush nested VM address space mapping in l1 hypervisor and it's to
reduce overhead of flushing ept tlb among vcpus. This patch is to
implement it.

Signed-off-by: Lan Tianyu 
---
 arch/x86/hyperv/Makefile   |  2 +-
 arch/x86/hyperv/nested.c   | 64 ++
 arch/x86/include/asm/hyperv-tlfs.h |  8 +
 arch/x86/include/asm/mshyperv.h|  2 ++
 4 files changed, 75 insertions(+), 1 deletion(-)
 create mode 100644 arch/x86/hyperv/nested.c

diff --git a/arch/x86/hyperv/Makefile b/arch/x86/hyperv/Makefile
index b173d404e3df..b21ee65c4101 100644
--- a/arch/x86/hyperv/Makefile
+++ b/arch/x86/hyperv/Makefile
@@ -1,2 +1,2 @@
-obj-y  := hv_init.o mmu.o
+obj-y  := hv_init.o mmu.o nested.o
 obj-$(CONFIG_X86_64)   += hv_apic.o
diff --git a/arch/x86/hyperv/nested.c b/arch/x86/hyperv/nested.c
new file mode 100644
index ..74dd38b5221d
--- /dev/null
+++ b/arch/x86/hyperv/nested.c
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Hyper-V nested virtualization code.
+ *
+ * Copyright (C) 2018, Microsoft, Inc.
+ *
+ * Author : Lan Tianyu 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ */
+
+
+#include 
+#include 
+#include 
+#include 
+
+int hyperv_flush_guest_mapping(u64 as)
+{
+   struct hv_guest_mapping_flush **flush_pcpu;
+   struct hv_guest_mapping_flush *flush;
+   u64 status;
+   unsigned long flags;
+   int ret = -EFAULT;
+
+   if (!hv_hypercall_pg)
+   goto fault;
+
+   local_irq_save(flags);
+
+   flush_pcpu = (struct hv_guest_mapping_flush **)
+   this_cpu_ptr(hyperv_pcpu_input_arg);
+
+   flush = *flush_pcpu;
+
+   if (unlikely(!flush)) {
+   local_irq_restore(flags);
+   goto fault;
+   }
+
+   flush->address_space = as;
+   flush->flags = 0;
+
+   status = hv_do_hypercall(HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE,
+flush, NULL);
+   local_irq_restore(flags);
+
+   if (!(status & HV_HYPERCALL_RESULT_MASK))
+   ret = 0;
+
+fault:
+   return ret;
+}
+EXPORT_SYMBOL_GPL(hyperv_flush_guest_mapping);
diff --git a/arch/x86/include/asm/hyperv-tlfs.h 
b/arch/x86/include/asm/hyperv-tlfs.h
index b8c89265baf0..08e24f552030 100644
--- a/arch/x86/include/asm/hyperv-tlfs.h
+++ b/arch/x86/include/asm/hyperv-tlfs.h
@@ -309,6 +309,7 @@ struct ms_hyperv_tsc_page {
 #define HV_X64_MSR_REENLIGHTENMENT_CONTROL 0x4106
 
 /* Nested features (CPUID 0x400A) EAX */
+#define HV_X64_NESTED_GUEST_MAPPING_FLUSH  BIT(18)
 #define HV_X64_NESTED_MSR_BITMAP   BIT(19)
 
 struct hv_reenlightenment_control {
@@ -350,6 +351,7 @@ struct hv_tsc_emulation_status {
 #define HVCALL_SEND_IPI_EX 0x0015
 #define HVCALL_POST_MESSAGE0x005c
 #define HVCALL_SIGNAL_EVENT0x005d
+#define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE 0x00af
 
 #define HV_X64_MSR_VP_ASSIST_PAGE_ENABLE   0x0001
 #define HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_SHIFT12
@@ -741,6 +743,12 @@ struct ipi_arg_ex {
struct hv_vpset vp_set;
 };
 
+/* HvFlushGuestPhysicalAddressSpace hypercalls */
+struct hv_guest_mapping_flush {
+   u64 address_space;
+   u64 flags;
+};
+
 /* HvFlushVirtualAddressSpace, HvFlushVirtualAddressList hypercalls */
 struct hv_tlb_flush {
u64 address_space;
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 3cd14311edfa..a6a615b49876 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -302,6 +302,7 @@ void hyperv_reenlightenment_intr(struct pt_regs *regs);
 void set_hv_tscchange_cb(void (*cb)(void));
 void clear_hv_tscchange_cb(void);
 void hyperv_stop_tsc_emulation(void);
+int hyperv_flush_guest_mapping(u64 as);
 
 #ifdef CONFIG_X86_64
 void hv_apic_init(void);
@@ -321,6 +322,7 @@ static inline struct hv_vp_assist_page 
*hv_get_vp_assist_page(unsigned int cpu)
 {
return NULL;
 }
+static inline int hyperv_flush_guest_mapping(u64 as) { return -1; }
 #endif /* CONFIG_HYPERV */
 
 #ifdef CONFIG_HYPERV_TSCPAGE
-- 
2.14.3
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 0/4] KVM/x86/hyper-V: Introduce PV guest address space mapping flush support

2018-07-02 Thread Tianyu Lan
Hyper-V provides a para-virtualization hypercall 
HvFlushGuestPhysicalAddressSpace
to flush nested VM address space mapping in l1 hypervisor and it's to reduce 
overhead
of flushing ept tlb among vcpus. The tradition way is to send IPIs to all 
affected
vcpus and executes INVEPT on each vcpus. It will trigger several vmexits for 
IPI and
INVEPT emulation. The pv hypercall can help to flush specified ept table on all 
vcpus
via one single hypercall.

Lan Tianyu (4):
  X86/Hyper-V: Add flush HvFlushGuestPhysicalAddressSpace hypercall
support
  KVM: Add tlb remote flush callback in kvm_x86_ops.
  KVM/VMX: Add identical ept table pointer check
  KVM/x86: Add tlb_remote_flush callback support for vmcs

 arch/x86/hyperv/Makefile   |  2 +-
 arch/x86/hyperv/nested.c   | 64 ++
 arch/x86/include/asm/hyperv-tlfs.h |  8 +
 arch/x86/include/asm/kvm_host.h|  1 +
 arch/x86/include/asm/mshyperv.h|  2 ++
 arch/x86/kvm/vmx.c | 56 +
 virt/kvm/kvm_main.c| 12 ++-
 7 files changed, 143 insertions(+), 2 deletions(-)
 create mode 100644 arch/x86/hyperv/nested.c
-- 
2.14.3
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [RFC Patch 1/3] X86/Hyper-V: Add flush HvFlushGuestPhysicalAddressSpace hypercall support

2018-06-05 Thread Tianyu Lan
Hi Michael:
Thanks for your review.

On 6/6/2018 12:59 AM, Michael Kelley (EOSG) wrote:
>> -Original Message-
>> From: linux-kernel-ow...@vger.kernel.org 
>>  On Behalf
>> Of Tianyu Lan
>> Sent: Monday, June 4, 2018 2:08 AM
>> Cc: Tianyu Lan ; KY Srinivasan 
>> ; Haiyang
>> Zhang ; Stephen Hemminger ;
>> t...@linutronix.de; mi...@redhat.com; h...@zytor.com; x...@kernel.org;
>> pbonz...@redhat.com; rkrc...@redhat.com; de...@linuxdriverproject.org; linux-
>> ker...@vger.kernel.org; k...@vger.kernel.org; vkuzn...@redhat.com
>> Subject: [RFC Patch 1/3] X86/Hyper-V: Add flush 
>> HvFlushGuestPhysicalAddressSpace hypercall
>> support
>>
>> Hyper-V provides a pv hypercall HvFlushGuestPhysicalAddressSpace to flush
>> nested VM address space mapping in l1 hypervisor and it's to reduce overhead
>> of flushing ept tlb among vcpus. This patch is to implement it.
>>
>> Signed-off-by: Lan Tianyu 
>> ---
>> diff --git a/arch/x86/hyperv/nested.c b/arch/x86/hyperv/nested.c
>> new file mode 100644
>> index ..17f7c288eccc
>> --- /dev/null
>> +++ b/arch/x86/hyperv/nested.c
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +
>> +int hyperv_flush_guest_mapping(u64 as)
>> +{
>> +struct hv_guest_mapping_flush **flush_pcpu;
>> +struct hv_guest_mapping_flush *flush;
>> +u64 status = U64_MAX;
> 
> Initializing status to U64_MAX doesn't seem necessary.
> 
>> +unsigned long flags;
>> +int ret = -EFAULT;
>> +
>> +if (!hv_hypercall_pg)
>> +goto fault;
>> +
>> +local_irq_save(flags);
>> +
>> +flush_pcpu = (struct hv_guest_mapping_flush **)
>> +this_cpu_ptr(hyperv_pcpu_input_arg);
>> +
>> +flush = *flush_pcpu;
>> +
>> +if (unlikely(!flush)) {
>> +local_irq_restore(flags);
>> +goto fault;
>> +}
>> +
>> +flush->address_space = as;
>> +flush->flags = 0;
>> +
>> +status = hv_do_hypercall(HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE,
>> + flush, NULL);
>> +local_irq_restore(flags);
>> +
>> +if (!(status & HV_HYPERCALL_RESULT_MASK))
>> +ret = 0;
>> +
>> +fault:
>> +return ret;
>> +}
>> +EXPORT_SYMBOL_GPL(hyperv_flush_guest_mapping);
>> diff --git a/arch/x86/include/asm/hyperv-tlfs.h 
>> b/arch/x86/include/asm/hyperv-tlfs.h
>> index b8c89265baf0..53bbeb08faea 100644
>> --- a/arch/x86/include/asm/hyperv-tlfs.h
>> +++ b/arch/x86/include/asm/hyperv-tlfs.h
>> @@ -309,6 +309,7 @@ struct ms_hyperv_tsc_page {
>>   #define HV_X64_MSR_REENLIGHTENMENT_CONTROL 0x4106
>>
>>   /* Nested features (CPUID 0x400A) EAX */
>> +#define HV_X64_NESTED_GUSET_MAPPING_FLUSH   BIT(18)
> 
> The #define name is misspelled.  "_GUSET_" should be "_GUEST_".
> And the matching usage in patch 3/3 will need to be updated as well.
> 
> Michael
> 

Nice catch! Will update.
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[RFC Patch 1/3] X86/Hyper-V: Add flush HvFlushGuestPhysicalAddressSpace hypercall support

2018-06-04 Thread Tianyu Lan
Hyper-V provides a pv hypercall HvFlushGuestPhysicalAddressSpace to flush
nested VM address space mapping in l1 hypervisor and it's to reduce overhead
of flushing ept tlb among vcpus. This patch is to implement it.

Signed-off-by: Lan Tianyu 
---
 arch/x86/hyperv/Makefile   |  2 +-
 arch/x86/hyperv/nested.c   | 64 ++
 arch/x86/include/asm/hyperv-tlfs.h |  8 +
 arch/x86/include/asm/mshyperv.h|  2 ++
 4 files changed, 75 insertions(+), 1 deletion(-)
 create mode 100644 arch/x86/hyperv/nested.c

diff --git a/arch/x86/hyperv/Makefile b/arch/x86/hyperv/Makefile
index b173d404e3df..b21ee65c4101 100644
--- a/arch/x86/hyperv/Makefile
+++ b/arch/x86/hyperv/Makefile
@@ -1,2 +1,2 @@
-obj-y  := hv_init.o mmu.o
+obj-y  := hv_init.o mmu.o nested.o
 obj-$(CONFIG_X86_64)   += hv_apic.o
diff --git a/arch/x86/hyperv/nested.c b/arch/x86/hyperv/nested.c
new file mode 100644
index ..17f7c288eccc
--- /dev/null
+++ b/arch/x86/hyperv/nested.c
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Hyper-V nested virtualization code.
+ *
+ * Copyright (C) 2018, Microsoft, Inc.
+ *
+ * Author : Lan Tianyu 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ */
+
+
+#include 
+#include 
+#include 
+#include 
+
+int hyperv_flush_guest_mapping(u64 as)
+{
+   struct hv_guest_mapping_flush **flush_pcpu;
+   struct hv_guest_mapping_flush *flush;
+   u64 status = U64_MAX;
+   unsigned long flags;
+   int ret = -EFAULT;
+
+   if (!hv_hypercall_pg)
+   goto fault;
+
+   local_irq_save(flags);
+
+   flush_pcpu = (struct hv_guest_mapping_flush **)
+   this_cpu_ptr(hyperv_pcpu_input_arg);
+
+   flush = *flush_pcpu;
+
+   if (unlikely(!flush)) {
+   local_irq_restore(flags);
+   goto fault;
+   }
+
+   flush->address_space = as;
+   flush->flags = 0;
+
+   status = hv_do_hypercall(HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE,
+flush, NULL);
+   local_irq_restore(flags);
+
+   if (!(status & HV_HYPERCALL_RESULT_MASK))
+   ret = 0;
+
+fault:
+   return ret;
+}
+EXPORT_SYMBOL_GPL(hyperv_flush_guest_mapping);
diff --git a/arch/x86/include/asm/hyperv-tlfs.h 
b/arch/x86/include/asm/hyperv-tlfs.h
index b8c89265baf0..53bbeb08faea 100644
--- a/arch/x86/include/asm/hyperv-tlfs.h
+++ b/arch/x86/include/asm/hyperv-tlfs.h
@@ -309,6 +309,7 @@ struct ms_hyperv_tsc_page {
 #define HV_X64_MSR_REENLIGHTENMENT_CONTROL 0x4106
 
 /* Nested features (CPUID 0x400A) EAX */
+#define HV_X64_NESTED_GUSET_MAPPING_FLUSH  BIT(18)
 #define HV_X64_NESTED_MSR_BITMAP   BIT(19)
 
 struct hv_reenlightenment_control {
@@ -350,6 +351,7 @@ struct hv_tsc_emulation_status {
 #define HVCALL_SEND_IPI_EX 0x0015
 #define HVCALL_POST_MESSAGE0x005c
 #define HVCALL_SIGNAL_EVENT0x005d
+#define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE 0x00af
 
 #define HV_X64_MSR_VP_ASSIST_PAGE_ENABLE   0x0001
 #define HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_SHIFT12
@@ -741,6 +743,12 @@ struct ipi_arg_ex {
struct hv_vpset vp_set;
 };
 
+/* HvFlushGuestPhysicalAddressSpace hypercalls */
+struct hv_guest_mapping_flush {
+   u64 address_space;
+   u64 flags;
+};
+
 /* HvFlushVirtualAddressSpace, HvFlushVirtualAddressList hypercalls */
 struct hv_tlb_flush {
u64 address_space;
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 3cd14311edfa..a6a615b49876 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -302,6 +302,7 @@ void hyperv_reenlightenment_intr(struct pt_regs *regs);
 void set_hv_tscchange_cb(void (*cb)(void));
 void clear_hv_tscchange_cb(void);
 void hyperv_stop_tsc_emulation(void);
+int hyperv_flush_guest_mapping(u64 as);
 
 #ifdef CONFIG_X86_64
 void hv_apic_init(void);
@@ -321,6 +322,7 @@ static inline struct hv_vp_assist_page 
*hv_get_vp_assist_page(unsigned int cpu)
 {
return NULL;
 }
+static inline int hyperv_flush_guest_mapping(u64 as) { return -1; }
 #endif /* CONFIG_HYPERV */
 
 #ifdef CONFIG_HYPERV_TSCPAGE
-- 
2.14.3
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[RFC Patch 0/3] KVM/x86/hyper-V: Introduce PV guest address space mapping flush support

2018-06-04 Thread Tianyu Lan
Hyper-V provides a para-virtualization hypercall 
HvFlushGuestPhysicalAddressSpace
to flush nested VM address space mapping in l1 hypervisor and it's to reduce 
overhead
of flushing ept tlb among vcpus. The tradition way is to send IPIs to all 
affected
vcpus and executes INVEPT on each vcpus. It will trigger several vmexits for 
IPI and
INVEPT emulation. The pv hypercall can help to flush specified ept table on all 
vcpus
via one single hypercall.

Lan Tianyu (3):
  X86/Hyper-V: Add flush HvFlushGuestPhysicalAddressSpace hypercall
support
  KVM: Add tlb remote flush callback in kvm_x86_ops.
  KVM/x86: Add tlb_remote_flush callback support for vmcs

 arch/x86/hyperv/Makefile   |  2 +-
 arch/x86/hyperv/nested.c   | 64 ++
 arch/x86/include/asm/hyperv-tlfs.h |  8 +
 arch/x86/include/asm/kvm_host.h|  1 +
 arch/x86/include/asm/mshyperv.h|  2 ++
 arch/x86/kvm/vmx.c | 15 +
 virt/kvm/kvm_main.c| 12 ++-
 7 files changed, 102 insertions(+), 2 deletions(-)
 create mode 100644 arch/x86/hyperv/nested.c

-- 
2.14.3
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH] HV: Fix definition of struct hv_vp_assist_page.

2018-05-21 Thread Tianyu Lan
The struct hv_vp_assist_page was defined incorrectly.
The "vtl_control" should be u64[3], "nested_enlightenments_control"
should be a u64 and there is 7 reserved bytes following "enlighten_vmentry".
This patch is to fix it.

Signed-off-by: Lan Tianyu 
---
 arch/x86/include/asm/hyperv-tlfs.h | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/arch/x86/include/asm/hyperv-tlfs.h 
b/arch/x86/include/asm/hyperv-tlfs.h
index f7be6d03a310..fae0a5431cdd 100644
--- a/arch/x86/include/asm/hyperv-tlfs.h
+++ b/arch/x86/include/asm/hyperv-tlfs.h
@@ -496,10 +496,11 @@ struct hv_timer_message_payload {
 /* Define virtual processor assist page structure. */
 struct hv_vp_assist_page {
__u32 apic_assist;
-   __u32 reserved;
-   __u64 vtl_control[2];
-   __u64 nested_enlightenments_control[2];
-   __u32 enlighten_vmentry;
+   __u32 reserved1;
+   __u64 vtl_control[3];
+   __u64 nested_enlightenments_control;
+   __u8 enlighten_vmentry;
+   __u8 reserved2[7];
__u64 current_nested_vmcs;
 };
 
-- 
2.14.3
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [Patch] vmbus: Simply hv_get_next_write_location() function

2018-01-25 Thread Tianyu Lan
On Thu, Jan 25, 2018 at 12:37 AM, Stephen Hemminger
<step...@networkplumber.org> wrote:
> On Wed, 24 Jan 2018 14:21:30 +0800
> lantianyu1...@gmail.com wrote:
>
>> From: Tianyu Lan <tianyu@microsoft.com>
>>
>> The "next" variable is redundant in hv_get_next_write_location().
>> This patch is to remove it and return write_index directly.
>>
>> Signed-off-by: Tianyu Lan <tianyu@microsoft.com>
>> ---
>>  drivers/hv/ring_buffer.c | 4 +---
>>  1 file changed, 1 insertion(+), 3 deletions(-)
>>
>> diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c
>> index 12eb8ca..71558e7 100644
>> --- a/drivers/hv/ring_buffer.c
>> +++ b/drivers/hv/ring_buffer.c
>> @@ -82,9 +82,7 @@ static void hv_signal_on_write(u32 old_write, struct 
>> vmbus_channel *channel)
>>  static inline u32
>>  hv_get_next_write_location(struct hv_ring_buffer_info *ring_info)
>>  {
>> - u32 next = ring_info->ring_buffer->write_index;
>> -
>> - return next;
>> + return ring_info->ring_buffer->write_index;
>>  }
>>
>>  /* Set the next write location for the specified ring buffer. */
>
> Looks good.
> But let's go farther since function is only used in one location in the file
> just eliminate it completely and do simple variable references.
>
> The get/set functions in this file are unnecessary.

Yes, agree and will update patch.

>
> Better still it is possible to replace the lock based ring structure
> with a compare-exchange solution.

There are several read/write operations of ring structure in the
hv_ringbuffer_write()
and these operations should be under protection. Especially for
ring_buffer->write_index,
we need to read it to calculate available write buffer, determine
write position and then update it after
writing buffer. This sequence should be under protection, right?

-- 
Best regards
Tianyu Lan
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel