Received: by 2002:a25:4158:0:0:0:0:0 with SMTP id o85csp2777090yba; Mon, 22 Apr 2019 12:46:29 -0700 (PDT) X-Google-Smtp-Source: APXvYqzp7ec0cle6Uqy6zjuKkR1ULb1DNdNIbnL8Ba2qgxUr8aeQ2IwwxIWaFH7cX6kZ/S+Edn/m X-Received: by 2002:a17:902:820c:: with SMTP id x12mr21294274pln.199.1555962389764; Mon, 22 Apr 2019 12:46:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1555962389; cv=none; d=google.com; s=arc-20160816; b=tQ8X1zJky5N4+iktxIrofkqTGwHhw33KtztL7a/6BCbIZjb1a0Rj889sKv8FClYb4F KnegCVd0GwQYCxpg/osNeti07CYmbTRwJZx+MjtLxzylpgLj+tMKvfXyYpe5W4w+T/6r onZCXZH1P2INLF6pk3M6CfjVhlmdsB7G1PQcdTT9W55T8A+z90c9uR+B7OOYngOMmM3H 8ujXpm4GmQT1mFaf2EzAm7VFU4jpvOLMIz34Xyrj4ClSavddQyy3Ltg0MG/HfjOwr7iU eFAvnT6c9K6WfNttXQvdH8o3bdO7XG7TME6wPeesMfBLeMZKw3kYug4PSci+ZS05h6S7 CpOw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=nmZtYeZDQ+nErRl3EhomZwKNertCQssrcZSJICunzVQ=; b=XKt+s9fb8S1QjIszyt2I5kkS4rPgOTRLM/MJOX+NPkzxzJYzlO2btcjsluskn+hZxI Bpk/7MvzdIwfdb79FaPnTFjZ2mSEzBQK7otoaw3Xzlm6i1kg9Vjws2X+oGHzNmfyBtAR 93Rh2MKsfDp0pcRpJXaH5blKh4ee3p3PKBBZiOmi8mTdcC8IIl22FSrpY5ycFVimgvZB lXZhmstQSgBJV5Rc8ENaf1b+dmElUyvuFT85krinSEXE8g+v89oFX55KVmNLwOk+TbgB 4HHnMDcA8y81IVkQOdmMwIvxbu3Ne/Pznz4biDxTxK3vw5zIwn+7n1SWEUYzbrwQsNwr YSuw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=M1lV0EfZ; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id p15si14265478pff.225.2019.04.22.12.46.14; Mon, 22 Apr 2019 12:46:29 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=M1lV0EfZ; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729607AbfDVToy (ORCPT + 99 others); Mon, 22 Apr 2019 15:44:54 -0400 Received: from mail.kernel.org ([198.145.29.99]:46218 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729094AbfDVTox (ORCPT ); Mon, 22 Apr 2019 15:44:53 -0400 Received: from sasha-vm.mshome.net (c-73-47-72-35.hsd1.nh.comcast.net [73.47.72.35]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 6259A218B0; Mon, 22 Apr 2019 19:44:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1555962293; bh=qngFFHZ2SQ9w9v6kUVMUKUePoEZlcPSTmI8gIwu10zo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=M1lV0EfZQ46WNCoAQSvXt3djLpwSivgRS+H98KJ7d9KntOSDs+0/KtBRrWqDjfAOP orajTDcjJx0WNg0hUIZqkWpmZ3jgzTg9JOqozo7TXcrbDUK0S4v8pmE+L1x4Pz8cHy 2P80i/UwEvcugci3PNsp4fjycDWWNte5uNg9+n+Q= From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Sean Christopherson , Paolo Bonzini , Sasha Levin , kvm@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH AUTOSEL 5.0 86/98] KVM: selftests: complete IO before migrating guest state Date: Mon, 22 Apr 2019 15:41:53 -0400 Message-Id: <20190422194205.10404-86-sashal@kernel.org> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190422194205.10404-1-sashal@kernel.org> References: <20190422194205.10404-1-sashal@kernel.org> MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Sean Christopherson [ Upstream commit 0f73bbc851ed32d22bbd86be09e0365c460bcd2e ] Documentation/virtual/kvm/api.txt states: NOTE: For KVM_EXIT_IO, KVM_EXIT_MMIO, KVM_EXIT_OSI, KVM_EXIT_PAPR and KVM_EXIT_EPR the corresponding operations are complete (and guest state is consistent) only after userspace has re-entered the kernel with KVM_RUN. The kernel side will first finish incomplete operations and then check for pending signals. Userspace can re-enter the guest with an unmasked signal pending to complete pending operations. Because guest state may be inconsistent, starting state migration after an IO exit without first completing IO may result in test failures, e.g. a proposed change to KVM's handling of %rip in its fast PIO handling[1] will cause the new VM, i.e. the post-migration VM, to have its %rip set to the IN instruction that triggered KVM_EXIT_IO, leading to a test assertion due to a stage mismatch. For simplicitly, require KVM_CAP_IMMEDIATE_EXIT to complete IO and skip the test if it's not available. The addition of KVM_CAP_IMMEDIATE_EXIT predates the state selftest by more than a year. [1] https://patchwork.kernel.org/patch/10848545/ Fixes: fa3899add1056 ("kvm: selftests: add basic test for state save and restore") Reported-by: Jim Mattson Signed-off-by: Sean Christopherson Signed-off-by: Paolo Bonzini Signed-off-by: Sasha Levin (Microsoft) --- tools/testing/selftests/kvm/include/kvm_util.h | 1 + tools/testing/selftests/kvm/lib/kvm_util.c | 16 ++++++++++++++++ .../testing/selftests/kvm/x86_64/state_test.c | 18 ++++++++++++++++-- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h index a84785b02557..07b71ad9734a 100644 --- a/tools/testing/selftests/kvm/include/kvm_util.h +++ b/tools/testing/selftests/kvm/include/kvm_util.h @@ -102,6 +102,7 @@ vm_paddr_t addr_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva); struct kvm_run *vcpu_state(struct kvm_vm *vm, uint32_t vcpuid); void vcpu_run(struct kvm_vm *vm, uint32_t vcpuid); int _vcpu_run(struct kvm_vm *vm, uint32_t vcpuid); +void vcpu_run_complete_io(struct kvm_vm *vm, uint32_t vcpuid); void vcpu_set_mp_state(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_mp_state *mp_state); void vcpu_regs_get(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_regs *regs); diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c index b52cfdefecbf..efa0aad8b3c6 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -1121,6 +1121,22 @@ int _vcpu_run(struct kvm_vm *vm, uint32_t vcpuid) return rc; } +void vcpu_run_complete_io(struct kvm_vm *vm, uint32_t vcpuid) +{ + struct vcpu *vcpu = vcpu_find(vm, vcpuid); + int ret; + + TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid); + + vcpu->state->immediate_exit = 1; + ret = ioctl(vcpu->fd, KVM_RUN, NULL); + vcpu->state->immediate_exit = 0; + + TEST_ASSERT(ret == -1 && errno == EINTR, + "KVM_RUN IOCTL didn't exit immediately, rc: %i, errno: %i", + ret, errno); +} + /* * VM VCPU Set MP State * diff --git a/tools/testing/selftests/kvm/x86_64/state_test.c b/tools/testing/selftests/kvm/x86_64/state_test.c index 4b3f556265f1..30f75856cf39 100644 --- a/tools/testing/selftests/kvm/x86_64/state_test.c +++ b/tools/testing/selftests/kvm/x86_64/state_test.c @@ -134,6 +134,11 @@ int main(int argc, char *argv[]) struct kvm_cpuid_entry2 *entry = kvm_get_supported_cpuid_entry(1); + if (!kvm_check_cap(KVM_CAP_IMMEDIATE_EXIT)) { + fprintf(stderr, "immediate_exit not available, skipping test\n"); + exit(KSFT_SKIP); + } + /* Create VM */ vm = vm_create_default(VCPU_ID, 0, guest_code); vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid()); @@ -156,8 +161,6 @@ int main(int argc, char *argv[]) stage, run->exit_reason, exit_reason_str(run->exit_reason)); - memset(®s1, 0, sizeof(regs1)); - vcpu_regs_get(vm, VCPU_ID, ®s1); switch (get_ucall(vm, VCPU_ID, &uc)) { case UCALL_ABORT: TEST_ASSERT(false, "%s at %s:%d", (const char *)uc.args[0], @@ -176,6 +179,17 @@ int main(int argc, char *argv[]) uc.args[1] == stage, "Unexpected register values vmexit #%lx, got %lx", stage, (ulong)uc.args[1]); + /* + * When KVM exits to userspace with KVM_EXIT_IO, KVM guarantees + * guest state is consistent only after userspace re-enters the + * kernel with KVM_RUN. Complete IO prior to migrating state + * to a new VM. + */ + vcpu_run_complete_io(vm, VCPU_ID); + + memset(®s1, 0, sizeof(regs1)); + vcpu_regs_get(vm, VCPU_ID, ®s1); + state = vcpu_save_state(vm, VCPU_ID); kvm_vm_release(vm); -- 2.19.1