From patchwork Mon Dec 18 19:06:35 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Adalbert_Laz=C4=83r?= X-Patchwork-Id: 10121727 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 1293F60390 for ; Mon, 18 Dec 2017 19:08:02 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0053228BCC for ; Mon, 18 Dec 2017 19:08:02 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E922D28C67; Mon, 18 Dec 2017 19:08:01 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3D5BB28BCC for ; Mon, 18 Dec 2017 19:08:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934361AbdLRTH7 (ORCPT ); Mon, 18 Dec 2017 14:07:59 -0500 Received: from mx02.bbu.dsd.mx.bitdefender.com ([91.199.104.133]:54690 "EHLO mx02.buh.bitdefender.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1760294AbdLRTHJ (ORCPT ); Mon, 18 Dec 2017 14:07:09 -0500 Comment: DomainKeys? See http://domainkeys.sourceforge.net/ DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=bitdefender.com; b=qCYAxCVeRScQa0/ujef8S/ChoydwnVCBhDM+3gVirgtNUmhlNFmna4YjrUeQjexEZnhFU/djtD9UwErd/eA6GZcPhyBXrTMNur9QEBX8Z+MBtvKIl9fjQ7fd/PYxqSmvRVkFRYlCK/rkY94ZOfn62RvBLV8sUdaTS6R9pjUwzZLp4zBCU6D+jjTrvs0NPq21uBIx+AS7MGt8/UlaAYrouLXGZM2/ZBRq5G3nmx3z8GANRLktKjy1bzhX20draRxQtiyvY/6rw+W/qvGm+67REMYmX+lSikFTw7wuqv/9wYNMazG0/BFumdbDXWtE8DLq62KeCCJ8EU0QroKu+Jz1kw==; h=Received:Received:Received:Received:From:To:Cc:Subject:Date:Message-Id:X-Mailer:In-Reply-To:References:MIME-Version:Content-Type:Content-Transfer-Encoding; DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=bitdefender.com; h=from:to :cc:subject:date:message-id:in-reply-to:references:mime-version :content-type:content-transfer-encoding; s=default; bh=E7eWKuVCD aoT7YXQKj5Cr1rPmm8=; b=SRZoZwzuYR+vGITUsfaQeDU/L7M7NVkzu0kOZ3Zsl Ch2yDaraedEKuTZ6KOat/NNDdYpuNKzbdGQO6vbxX0ViI/+SBiP7OcslRWhSED+I vzO1hDT3xqfjrvQJxrZHzQTuro4nNh74I+ESRd2Sn78MSXUOKTDkGaDK2S5hzRG5 TQPtVgUbv3Kpm1MJpJBF2XnePtfreyBqNaTRD6/65ssfl61GeiJiyObFJ/brGp2+ HKFH3wQXmqgIzg8ao7gLwDAu2yBEcv8bhiIpN5Rr4cY4LHtXjJc/uq/K8oyMU1pA BQ/js72swX3mCT1oCnvx7Nlil67XvPFShbc0OiDWT8+cw== Received: (qmail 30854 invoked from network); 18 Dec 2017 21:06:57 +0200 Received: from mx-robo.bitdefender.biz (HELO mx01robo.bbu.dsd.mx.bitdefender.com) (10.17.80.60) by mx02.buh.bitdefender.com with AES128-GCM-SHA256 encrypted SMTP; 18 Dec 2017 21:06:57 +0200 Received: (qmail 31396 invoked from network); 18 Dec 2017 21:06:57 +0200 Received: from unknown (HELO host.bbu.bitdefender.biz) (10.10.193.111) by mx01robo.bbu.dsd.mx.bitdefender.com with SMTP; 18 Dec 2017 21:06:57 +0200 From: =?UTF-8?q?Adalber=20Laz=C4=83r?= To: kvm@vger.kernel.org Cc: linux-mm@kvack.org, Paolo Bonzini , =?UTF-8?q?Radim=20Kr=C4=8Dm=C3=A1=C5=99?= , Xiao Guangrong , =?UTF-8?q?Mihai=20Don=C8=9Bu?= , Adalbert Lazar , =?UTF-8?q?Nicu=C8=99or=20C=C3=AE=C8=9Bu?= Subject: [RFC PATCH v4 11/18] kvm: x86: hook in the page tracking Date: Mon, 18 Dec 2017 21:06:35 +0200 Message-Id: <20171218190642.7790-12-alazar@bitdefender.com> X-Mailer: git-send-email 2.14.2 In-Reply-To: <20171218190642.7790-1-alazar@bitdefender.com> References: <20171218190642.7790-1-alazar@bitdefender.com> MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Adalbert Lazar Inform the guest introspection tool that a read/write/execute access is happening on a page of interest (configured via a KVMI_SET_PAGE_ACCESS request). The introspection tool can respond to allow the emulation to continue, with or without custom input (for read access), retry to guest (if the tool has changed the program counter, has emulated the instruction or the page is no longer of interest). Signed-off-by: Mihai Donțu Signed-off-by: Nicușor Cîțu --- arch/x86/include/asm/kvm_emulate.h | 1 + arch/x86/kvm/emulate.c | 9 +++++++- arch/x86/kvm/mmu.c | 3 +++ arch/x86/kvm/x86.c | 46 +++++++++++++++++++++++++++++--------- 4 files changed, 48 insertions(+), 11 deletions(-) diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h index b24b1c8b3979..e257cae3a745 100644 --- a/arch/x86/include/asm/kvm_emulate.h +++ b/arch/x86/include/asm/kvm_emulate.h @@ -438,6 +438,7 @@ bool x86_page_table_writing_insn(struct x86_emulate_ctxt *ctxt); #define EMULATION_OK 0 #define EMULATION_RESTART 1 #define EMULATION_INTERCEPTED 2 +#define EMULATION_USER_EXIT 3 void init_decode_cache(struct x86_emulate_ctxt *ctxt); int x86_emulate_insn(struct x86_emulate_ctxt *ctxt); int emulator_task_switch(struct x86_emulate_ctxt *ctxt, diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index abe74f779f9d..94886040f8f1 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -5263,7 +5263,12 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len) ctxt->memopp->addr.mem.ea + ctxt->_eip); done: - return (rc != X86EMUL_CONTINUE) ? EMULATION_FAILED : EMULATION_OK; + if (rc == X86EMUL_RETRY_INSTR) + return EMULATION_USER_EXIT; + else if (rc == X86EMUL_CONTINUE) + return EMULATION_OK; + else + return EMULATION_FAILED; } bool x86_page_table_writing_insn(struct x86_emulate_ctxt *ctxt) @@ -5633,6 +5638,8 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt) if (rc == X86EMUL_INTERCEPTED) return EMULATION_INTERCEPTED; + if (rc == X86EMUL_RETRY_INSTR) + return EMULATION_USER_EXIT; if (rc == X86EMUL_CONTINUE) writeback_registers(ctxt); diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 19dc17b00db2..18205c710233 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -5066,6 +5066,9 @@ int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, u64 error_code, if (mmio_info_in_cache(vcpu, cr2, direct)) emulation_type = 0; + if (kvm_page_track_is_active(vcpu, gpa_to_gfn(cr2), + KVM_PAGE_TRACK_PREEXEC)) + emulation_type = EMULTYPE_NO_REEXECUTE; emulate: er = x86_emulate_instruction(vcpu, cr2, emulation_type, insn, insn_len); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 9889e96f64e6..caf50b7307a4 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4501,6 +4501,9 @@ static int kvm_fetch_guest_virt(struct x86_emulate_ctxt *ctxt, if (unlikely(gpa == UNMAPPED_GVA)) return X86EMUL_PROPAGATE_FAULT; + if (!kvm_page_track_preexec(vcpu, gpa)) + return X86EMUL_RETRY_INSTR; + offset = addr & (PAGE_SIZE-1); if (WARN_ON(offset + bytes > PAGE_SIZE)) bytes = (unsigned)PAGE_SIZE - offset; @@ -4622,13 +4625,26 @@ static int vcpu_mmio_gva_to_gpa(struct kvm_vcpu *vcpu, unsigned long gva, int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa, const void *val, int bytes) { - int ret; - - ret = kvm_vcpu_write_guest(vcpu, gpa, val, bytes); - if (ret < 0) - return 0; + if (!kvm_page_track_prewrite(vcpu, gpa, val, bytes)) + return X86EMUL_RETRY_INSTR; + if (kvm_vcpu_write_guest(vcpu, gpa, val, bytes) < 0) + return X86EMUL_UNHANDLEABLE; kvm_page_track_write(vcpu, gpa, val, bytes); - return 1; + return X86EMUL_CONTINUE; +} + +static int emulator_read_phys(struct kvm_vcpu *vcpu, gpa_t gpa, + void *val, int bytes) +{ + bool data_ready; + + if (!kvm_page_track_preread(vcpu, gpa, val, bytes, &data_ready)) + return X86EMUL_RETRY_INSTR; + if (data_ready) + return X86EMUL_CONTINUE; + if (kvm_vcpu_read_guest(vcpu, gpa, val, bytes) < 0) + return X86EMUL_UNHANDLEABLE; + return X86EMUL_CONTINUE; } struct read_write_emulator_ops { @@ -4658,7 +4674,7 @@ static int read_prepare(struct kvm_vcpu *vcpu, void *val, int bytes) static int read_emulate(struct kvm_vcpu *vcpu, gpa_t gpa, void *val, int bytes) { - return !kvm_vcpu_read_guest(vcpu, gpa, val, bytes); + return emulator_read_phys(vcpu, gpa, val, bytes); } static int write_emulate(struct kvm_vcpu *vcpu, gpa_t gpa, @@ -4733,8 +4749,11 @@ static int emulator_read_write_onepage(unsigned long addr, void *val, return X86EMUL_PROPAGATE_FAULT; } - if (!ret && ops->read_write_emulate(vcpu, gpa, val, bytes)) - return X86EMUL_CONTINUE; + if (!ret) { + ret = ops->read_write_emulate(vcpu, gpa, val, bytes); + if (ret == X86EMUL_CONTINUE || ret == X86EMUL_RETRY_INSTR) + return ret; + } /* * Is this MMIO handled locally? @@ -4869,6 +4888,9 @@ static int emulator_cmpxchg_emulated(struct x86_emulate_ctxt *ctxt, if (is_error_page(page)) goto emul_write; + if (!kvm_page_track_prewrite(vcpu, gpa, new, bytes)) + return X86EMUL_RETRY_INSTR; + kaddr = kmap_atomic(page); kaddr += offset_in_page(gpa); switch (bytes) { @@ -5721,7 +5743,9 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, trace_kvm_emulate_insn_start(vcpu); ++vcpu->stat.insn_emulation; - if (r != EMULATION_OK) { + if (r == EMULATION_USER_EXIT) + return EMULATE_DONE; + if (r != EMULATION_OK) { if (emulation_type & EMULTYPE_TRAP_UD) return EMULATE_FAIL; if (reexecute_instruction(vcpu, cr2, write_fault_to_spt, @@ -5758,6 +5782,8 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, r = x86_emulate_insn(ctxt); + if (r == EMULATION_USER_EXIT) + return EMULATE_DONE; if (r == EMULATION_INTERCEPTED) return EMULATE_DONE;