mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Tang Chen <tangchen@cn.fujitsu.com>
To: <gleb@kernel.org>, <mtosatti@redhat.com>, <nadav.amit@gmail.com>,
	<jan.kiszka@web.de>, <pbonzini@redhat.com>
Cc: <kvm@vger.kernel.org>, <laijs@cn.fujitsu.com>,
	<isimatu.yasuaki@jp.fujitsu.com>, <guz.fnst@cn.fujitsu.com>,
	<linux-kernel@vger.kernel.org>, <tangchen@cn.fujitsu.com>
Subject: [PATCH v8 4/8] kvm, mem-hotplug: Reload L1's apic access page in vcpu_enter_guest().
Date: Wed, 24 Sep 2014 15:57:54 +0800	[thread overview]
Message-ID: <1411545478-9848-5-git-send-email-tangchen@cn.fujitsu.com> (raw)
In-Reply-To: <1411545478-9848-1-git-send-email-tangchen@cn.fujitsu.com>

We wants to migrate apic access page pinned by guest (L1 and L2) to make memory
hotplug available.

There are two situations need to be handled for apic access page used by L2 vm:
1. L1 prepares a separate apic access page for L2.

   L2 pins a lot of pages in memory. Even if we can migrate apic access page,
   memory hotplug is not available when L2 is running. So do not handle this
   now. Migrate L1's apic access page only.

2. L1 and L2 share one apic access page.

   Since we will migrate L1's apic access page, we should do some handling when
   migration happens in the following situations:

   1) when L0 is running: Update L1's vmcs in the next L0->L1 entry and L2's
      vmcs in the next L1->L2 entry.

   2) when L1 is running: Force a L1->L0 exit, update L1's vmcs in the next
      L0->L1 entry and L2's vmcs in the next L1->L2 entry.

   3) when L2 is running: Force a L2->L0 exit, update L2's vmcs in the next
      L0->L2 entry and L1's vmcs in the next L2->L1 exit.

This patch handles 1) and 2).

Since we don't handle L1 ans L2 have separate apic access pages situation,
when we update vmcs, we need to check if we are in L2 and if L1 prepares an
non-shared apic access page for L2. We do this in vmx_set_apic_access_page_addr()
when trying to set new apic access page's hpa like this:

       if (!is_guest_mode(vcpu) ||
           !(vmx->nested.current_vmcs12->secondary_vm_exec_control &
             SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES))

Signed-off-by: Tang Chen <tangchen@cn.fujitsu.com>
---
 arch/x86/include/asm/kvm_host.h |  1 +
 arch/x86/kvm/vmx.c              | 39 ++++++++++++++++++++++++++++++++++++++-
 arch/x86/kvm/x86.c              | 23 +++++++++++++++++++++++
 include/linux/kvm_host.h        |  1 +
 4 files changed, 63 insertions(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 35171c7..582cd0f 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -739,6 +739,7 @@ struct kvm_x86_ops {
 	void (*hwapic_isr_update)(struct kvm *kvm, int isr);
 	void (*load_eoi_exitmap)(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap);
 	void (*set_virtual_x2apic_mode)(struct kvm_vcpu *vcpu, bool set);
+	void (*set_apic_access_page_addr)(struct kvm_vcpu *vcpu, hpa_t hpa);
 	void (*deliver_posted_interrupt)(struct kvm_vcpu *vcpu, int vector);
 	void (*sync_pir_to_irr)(struct kvm_vcpu *vcpu);
 	int (*set_tss_addr)(struct kvm *kvm, unsigned int addr);
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 72a0470..1411bab 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -3108,9 +3108,17 @@ static __init int hardware_setup(void)
 	if (!cpu_has_vmx_unrestricted_guest())
 		enable_unrestricted_guest = 0;
 
-	if (!cpu_has_vmx_flexpriority())
+	if (!cpu_has_vmx_flexpriority()) {
 		flexpriority_enabled = 0;
 
+		/*
+		 * set_apic_access_page_addr() is used to reload apic access
+		 * page in case it is migrated for memory hotplug reason. If
+		 * platform doesn't have this affinity, no need to handle it.
+		 */
+		kvm_x86_ops->set_apic_access_page_addr = NULL;
+	}
+
 	if (!cpu_has_vmx_tpr_shadow())
 		kvm_x86_ops->update_cr8_intercept = NULL;
 
@@ -7090,6 +7098,34 @@ static void vmx_set_virtual_x2apic_mode(struct kvm_vcpu *vcpu, bool set)
 	vmx_set_msr_bitmap(vcpu);
 }
 
+static void vmx_set_apic_access_page_addr(struct kvm_vcpu *vcpu, hpa_t hpa)
+{
+	struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+	/*
+	 * This function is used to reload apic access page in case it is
+	 * migrated for memory hotplug reason. And only L1 and L2 share the
+	 * same apic access page situation is handled.
+	 *
+	 * 1) If vcpu is not in guest mode (in L1), reload the page for L1.
+	 *    And L2's page will be reloaded in the next L1->L2 entry by
+	 *    prepare_vmcs02().
+	 *
+	 * 2) If vcpu is in guest mode (in L2), but L1 didn't not prepare an
+	 *    apic access page for L2 (current_vmcs12->secondary_vm_exec_control
+	 *    does not have SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES bit set),
+	 *    reload the page for L2.
+	 *    And L1's page will be reloaded in the next L2->L1 exit.
+	 *
+	 * 3) Otherwise, do nothing. L2's specific apic access page is still
+	 *    pinned in memory, and not hotpluggable.
+	 */
+	if (!is_guest_mode(vcpu) ||
+	    !(vmx->nested.current_vmcs12->secondary_vm_exec_control &
+	      SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES))
+		vmcs_write64(APIC_ACCESS_ADDR, hpa);
+}
+
 static void vmx_hwapic_isr_update(struct kvm *kvm, int isr)
 {
 	u16 status;
@@ -8909,6 +8945,7 @@ static struct kvm_x86_ops vmx_x86_ops = {
 	.enable_irq_window = enable_irq_window,
 	.update_cr8_intercept = update_cr8_intercept,
 	.set_virtual_x2apic_mode = vmx_set_virtual_x2apic_mode,
+	.set_apic_access_page_addr = vmx_set_apic_access_page_addr,
 	.vm_has_apicv = vmx_vm_has_apicv,
 	.load_eoi_exitmap = vmx_load_eoi_exitmap,
 	.hwapic_irr_update = vmx_hwapic_irr_update,
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index e05bd58..1f0c99a 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -5989,6 +5989,27 @@ static void vcpu_scan_ioapic(struct kvm_vcpu *vcpu)
 	kvm_apic_update_tmr(vcpu, tmr);
 }
 
+static void kvm_vcpu_reload_apic_access_page(struct kvm_vcpu *vcpu)
+{
+	/*
+	 * If platform doesn't have 2nd exec virtualize apic access affinity,
+	 * set_apic_access_page_addr() will be set to NULL in hardware_setup(),
+	 * and no need to reload apic access page here.
+	 */
+	if (!kvm_x86_ops->set_apic_access_page_addr)
+		return;
+
+	/*
+	 * APIC access page could be migrated. When the page is being
+	 * migrated, GUP will wait till the migrate entry is replaced
+	 * with the new pte entry pointing to the new page.
+	 */
+	vcpu->kvm->arch.apic_access_page = gfn_to_page(vcpu->kvm,
+			APIC_DEFAULT_PHYS_BASE >> PAGE_SHIFT);
+	kvm_x86_ops->set_apic_access_page_addr(vcpu,
+			page_to_phys(vcpu->kvm->arch.apic_access_page));
+}
+
 /*
  * Returns 1 to let __vcpu_run() continue the guest execution loop without
  * exiting to the userspace.  Otherwise, the value will be returned to the
@@ -6049,6 +6070,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
 			kvm_deliver_pmi(vcpu);
 		if (kvm_check_request(KVM_REQ_SCAN_IOAPIC, vcpu))
 			vcpu_scan_ioapic(vcpu);
+		if (kvm_check_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu))
+			kvm_vcpu_reload_apic_access_page(vcpu);
 	}
 
 	if (kvm_check_request(KVM_REQ_EVENT, vcpu) || req_int_win) {
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index a4c33b3..c23236a 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -136,6 +136,7 @@ static inline bool is_error_page(struct page *page)
 #define KVM_REQ_GLOBAL_CLOCK_UPDATE 22
 #define KVM_REQ_ENABLE_IBS        23
 #define KVM_REQ_DISABLE_IBS       24
+#define KVM_REQ_APIC_PAGE_RELOAD  25
 
 #define KVM_USERSPACE_IRQ_SOURCE_ID		0
 #define KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID	1
-- 
1.8.3.1


  parent reply	other threads:[~2014-09-24  7:58 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-09-24  7:57 [PATCH v8 0/8] kvm, mem-hotplug: Do not pin ept identity pagetable and apic access page Tang Chen
2014-09-24  7:57 ` [PATCH v8 1/8] kvm: Use APIC_DEFAULT_PHYS_BASE macro as the apic access page address Tang Chen
2014-09-24  7:57 ` [PATCH v8 2/8] kvm: Remove ept_identity_pagetable from struct kvm_arch Tang Chen
2014-09-24  7:57 ` [PATCH v8 3/8] kvm: Make init_rmode_identity_map() return 0 on success Tang Chen
2014-09-24  7:57 ` Tang Chen [this message]
2014-09-24 11:44   ` [PATCH v8 4/8] kvm, mem-hotplug: Reload L1's apic access page in vcpu_enter_guest() Paolo Bonzini
2014-09-24  7:57 ` [PATCH v8 5/8] kvm: Rename make_all_cpus_request() to kvm_make_all_cpus_request() and make it non-static Tang Chen
2014-09-24  7:57 ` [PATCH v8 6/8] kvm, mem-hotplug: Reload L1's apic access page on migration when L2 is running Tang Chen
2014-09-24  7:57 ` [PATCH v8 7/8] kvm, mem-hotplug: Add arch specific mmu notifier to handle apic access migration Tang Chen
2014-09-24  7:57 ` [PATCH v8 8/8] kvm, mem-hotplug: Unpin and remove kvm_arch->apic_access_page Tang Chen
2014-09-24  8:20 ` [PATCH v8 0/8] kvm, mem-hotplug: Do not pin ept identity pagetable and apic access page Paolo Bonzini
2014-09-24  8:25   ` Tang Chen
2014-09-25  8:19   ` Tang Chen
2014-09-25 13:43     ` Paolo Bonzini
2014-09-26  1:21       ` Tang Chen
2014-09-26  8:13         ` Paolo Bonzini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1411545478-9848-5-git-send-email-tangchen@cn.fujitsu.com \
    --to=tangchen@cn.fujitsu.com \
    --cc=gleb@kernel.org \
    --cc=guz.fnst@cn.fujitsu.com \
    --cc=isimatu.yasuaki@jp.fujitsu.com \
    --cc=jan.kiszka@web.de \
    --cc=kvm@vger.kernel.org \
    --cc=laijs@cn.fujitsu.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mtosatti@redhat.com \
    --cc=nadav.amit@gmail.com \
    --cc=pbonzini@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®