From patchwork Tue Apr 26 19:25:03 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Cao, Lei" X-Patchwork-Id: 8943391 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id B62569F441 for ; Tue, 26 Apr 2016 19:25:15 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 9A31B200DB for ; Tue, 26 Apr 2016 19:25:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 30DE92013D for ; Tue, 26 Apr 2016 19:25:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752995AbcDZTZJ (ORCPT ); Tue, 26 Apr 2016 15:25:09 -0400 Received: from mail-by2on0148.outbound.protection.outlook.com ([207.46.100.148]:27028 "EHLO na01-by2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1753293AbcDZTZH convert rfc822-to-8bit (ORCPT ); Tue, 26 Apr 2016 15:25:07 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=StratusTechnologies.onmicrosoft.com; s=selector1-stratus-com; h=From:To:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=/a0p7iivQc+YcKd3/7iR3STjkaCzbmz60E7dZOfcy0U=; b=k0eu1eT/ffJsY1awa0iD+9gdqxZ3INvhYisZgt+bL3leRttu/64QACw+iTSgcuJbcsQbmdnul2b2uOh/APOH9qcOj1LbE/8zoHfBUytsygiRVCbGuwsjTF+wujFu480aJcGZi1lx7kEu0EoaUc0ysXaj8fbGlcqSvRHj4XKJs0Y= Received: from BL2PR08MB481.namprd08.prod.outlook.com (10.141.93.14) by BL2PR08MB483.namprd08.prod.outlook.com (10.141.93.23) with Microsoft SMTP Server (TLS) id 15.1.466.19; Tue, 26 Apr 2016 19:25:03 +0000 Received: from BL2PR08MB481.namprd08.prod.outlook.com ([10.141.93.14]) by BL2PR08MB481.namprd08.prod.outlook.com ([10.141.93.14]) with mapi id 15.01.0485.005; Tue, 26 Apr 2016 19:25:03 +0000 From: "Cao, Lei" To: Paolo Bonzini , =?iso-8859-2?Q?Radim_Kr=E8m=E1=F8?= , "kvm@vger.kernel.org" Subject: [PATCH 4/6] KVM: Dirty memory tracking for performant checkpointing and improved live migration Thread-Topic: [PATCH 4/6] KVM: Dirty memory tracking for performant checkpointing and improved live migration Thread-Index: AQHRn/FV+mrQEDF9vUiCJYPgu09uSw== Date: Tue, 26 Apr 2016 19:25:03 +0000 Message-ID: References: <201604261855.u3QItv3P024443@dev1.sn.stratus.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: redhat.com; dkim=none (message not signed) header.d=none; redhat.com; dmarc=none action=none header.from=stratus.com; x-originating-ip: [198.97.42.5] x-ms-office365-filtering-correlation-id: 7471ce1b-1614-4782-0861-08d36e0877c3 x-microsoft-exchange-diagnostics: 1; BL2PR08MB483; 5:rqsNw42/Ejrl4DiMYVvKxN5PqiBIx3ELtj64N1bTdcEjSuFzeye+QyG4An1iIcEUPr6RkkPIihXTDX7iKpsJuS/4CTPIc09ZN2k/aab5mWeZVTJQhbYPkZzV+wF0WyLAdthGsjRXq2Xoq/7sqHnuZFF9ITcs27Wnz1DN/yUHxNsIqbANzal1QqcrtWwQDqn9; 24:O9IExsShPgS3HWgUA+qQJB3+p4ZaxAt/5FNSFwuosRHpjMwdmqBf8U4hn+WHkfsgpb7n5CZHSUrE54KTiFypKANfSgQAOEdLwnEC2lSkhKE=; 7:grZn9///kCoeUU/Zb/KVllhHVmGr295Qz0oRPuza04P1sVoQeIOHJV0sZDt+9MQ6mwMHXBNeDyBXuiZex444/aI0ZcECiNZ018A06+4f0rBtPCzmAbGcjAFgZIkprkZ92qwrSjdalMjorh5f8fDDvcncFKJRPK0UVoxBXv1uBt5wDBxzNy6lPo33Z62miQoAMC5UX52ENHUkfV1xr8OrdztjSJn8/FY+Ilsp/2S7v3U=; 20:HJ4hI8X/RcXlgFYxGIBclMb45KOLKrdkTHXw7Vz4kmSwHLpyN05CMIgIFznXRBJ98r00o7nsGFH+ZgUeijljf2S5IOFRntPWN55dvGLcePwSVD6CKP/EozS+3cu3g3t+b9M9BwgiRIZCJYzayCHO8miKZOO08/9DwV6cIt5uluc= x-microsoft-antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BL2PR08MB483; x-microsoft-antispam-prvs: x-exchange-antispam-report-test: UriScan:; x-exchange-antispam-report-cfa-test: BCL:0; PCL:0; RULEID:(9101521072)(601004)(2401047)(5005006)(8121501046)(10201501046)(3002001); SRVR:BL2PR08MB483; BCL:0; PCL:0; RULEID:; SRVR:BL2PR08MB483; x-forefront-prvs: 0924C6A0D5 x-forefront-antispam-report: SFV:NSPM; SFS:(10019020)(6009001)(66066001)(5001770100001)(229853001)(87936001)(102836003)(86362001)(5008740100001)(107886002)(189998001)(74316001)(33656002)(10400500002)(3280700002)(106116001)(99286002)(3660700001)(1220700001)(81166005)(5003600100002)(5002640100001)(76176999)(76576001)(122556002)(9686002)(5004730100002)(11100500001)(6116002)(92566002)(77096005)(54356999)(2501003)(50986999)(2906002)(586003)(19580395003)(19580405001)(1096002)(2900100001)(21314002)(14143004); DIR:OUT; SFP:1102; SCL:1; SRVR:BL2PR08MB483; H:BL2PR08MB481.namprd08.prod.outlook.com; FPR:; SPF:None; MLV:sfv; LANG:en; spamdiagnosticoutput: 1:23 spamdiagnosticmetadata: NSPM MIME-Version: 1.0 X-OriginatorOrg: stratus.com X-MS-Exchange-CrossTenant-originalarrivaltime: 26 Apr 2016 19:25:03.4779 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: de36b473-b8ad-46ff-837f-9da16b8d1b77 X-MS-Exchange-Transport-CrossTenantHeadersStamped: BL2PR08MB483 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Spam-Status: No, score=-7.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Implement a dirty page threshold which when triggered forces vcpus to exit. Due to limited buffering on the host, it should be ensured that checkpoint state is captured before too many pages have been dirtied. Exceeding buffer space would effectively force the two sides to be broken apart and be resynchronized from scratch. This "divergence" event is costly to repair. Given that, an "emergency" stop is needed so that once a critical threshold of dirty pages has been reached, if the VM execution has not been stopped, VM exits with a new exit reason indicating that the dirty log is full. This only kicks in after a predefined threshold of dirty pages has been reached and the threshold and buffer sizes are selected to make the use of the "emergency stop" a rare event. Signed-off-by: Lei Cao --- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/x86.c | 11 ++++++++++ include/linux/kvm_host.h | 1 + include/uapi/linux/kvm.h | 1 + virt/kvm/kvm_main.c | 34 ++++++++++++++++++++++++++++++- 5 files changed, 47 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 52bff2b..2b43660 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -71,6 +71,7 @@ #define KVM_REQ_HV_RESET 28 #define KVM_REQ_HV_EXIT 29 #define KVM_REQ_HV_STIMER 30 +#define KVM_REQ_EXIT_DIRTY_LOG_FULL 31 #define CR0_RESERVED_BITS \ (~(unsigned long)(X86_CR0_PE | X86_CR0_MP | X86_CR0_EM | X86_CR0_TS \ diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 9b7798c..deede71 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -6489,6 +6489,11 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) r = 1; goto out; } + if (kvm_check_request(KVM_REQ_EXIT_DIRTY_LOG_FULL, vcpu)) { + vcpu->run->exit_reason = KVM_EXIT_DIRTY_LOG_FULL; + r = 0; + goto out; + } if (kvm_check_request(KVM_REQ_STEAL_UPDATE, vcpu)) record_steal_time(vcpu); if (kvm_check_request(KVM_REQ_SMI, vcpu)) @@ -6687,6 +6692,12 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu); + if (vcpu->need_exit) { + vcpu->need_exit = false; + kvm_make_all_cpus_request(vcpu->kvm, + KVM_REQ_EXIT_DIRTY_LOG_FULL); + } + /* * Profile KVM exit RIPs: */ diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 5793ecf..08bda35 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -257,6 +257,7 @@ struct kvm_vcpu { } spin_loop; #endif bool preempted; + bool need_exit; struct kvm_vcpu_arch arch; }; diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 736668d..97520c4 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -205,6 +205,7 @@ struct kvm_hyperv_exit { #define KVM_EXIT_S390_STSI 25 #define KVM_EXIT_IOAPIC_EOI 26 #define KVM_EXIT_HYPERV 27 +#define KVM_EXIT_DIRTY_LOG_FULL 28 /* For KVM_EXIT_INTERNAL_ERROR */ /* Emulate instruction failed. */ diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index ba99cbc6..e22d7f4 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -2006,6 +2006,25 @@ static void mark_page_dirty_in_slot(struct kvm_memory_slot *memslot, } } +static void check_dirty_trigger(struct kvm *kvm, struct kvm_vcpu *vcpu, + int count) +{ + if (count > kvm->mt.dirty_trigger) { + /* + * Request vcpu exits, but if interrupts are disabled, we have + * to defer the requests because smp_call_xxx may deadlock when + * called that way. + */ + if (vcpu && irqs_disabled()) { + vcpu->need_exit = 1; + } else { + WARN_ON(irqs_disabled()); + kvm_make_all_cpus_request(kvm, + KVM_REQ_EXIT_DIRTY_LOG_FULL); + } + } +} + /* * We have some new dirty pages for our sublist waiter. Enough to merit * waking it up? @@ -2079,6 +2098,7 @@ static void mt_mark_page_dirty(struct kvm *kvm, struct kvm_memory_slot *slot, if ((gfnlist->dirty_index % DIRTY_GFN_ADD_GRANULARITY) == 0) { spin_lock(&kvm->mt.lock); kvm->mt.tot_pages += DIRTY_GFN_ADD_GRANULARITY; + check_dirty_trigger(kvm, vcpu, kvm->mt.tot_pages); mt_sw_add_pages(kvm); spin_unlock(&kvm->mt.lock); } @@ -2433,6 +2453,8 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id) if (IS_ERR(vcpu)) return PTR_ERR(vcpu); + vcpu->need_exit = false; + preempt_notifier_init(&vcpu->preempt_notifier, &kvm_preempt_ops); r = kvm_arch_vcpu_setup(vcpu); @@ -3627,7 +3649,17 @@ static int kvm_vm_ioctl_mt_sublist_fetch(struct kvm *kvm, static int kvm_vm_ioctl_mt_dirty_trigger(struct kvm *kvm, int dirty_trigger) { - return -EINVAL; + if (!kvm->mt.gfn_list.dirty_gfns) + return -EINVAL; + + if (kvm->mt.gfn_list.max_dirty < dirty_trigger) + return -EINVAL; + + kvm->mt.dirty_trigger = dirty_trigger; + + check_dirty_trigger(kvm, NULL, kvm->mt.tot_pages); + + return 0; } static long kvm_vm_ioctl(struct file *filp,