From patchwork Mon Aug 28 01:56:51 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?UTF-8?q?Sergio=20Andr=C3=A9s=20G=C3=B3mez=20Del=20Real?= X-Patchwork-Id: 9924051 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 E3DF56035E for ; Mon, 28 Aug 2017 02:01:47 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D5BE328672 for ; Mon, 28 Aug 2017 02:01:47 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CA91A28674; Mon, 28 Aug 2017 02:01:47 +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=-6.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 3602328672 for ; Mon, 28 Aug 2017 02:01:47 +0000 (UTC) Received: from localhost ([::1]:36510 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dm9N4-0007Qc-Ed for patchwork-qemu-devel@patchwork.kernel.org; Sun, 27 Aug 2017 22:01:46 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42107) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dm9JD-00054b-Vc for qemu-devel@nongnu.org; Sun, 27 Aug 2017 21:57:49 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dm9JC-0001FR-SU for qemu-devel@nongnu.org; Sun, 27 Aug 2017 21:57:48 -0400 Received: from mail-ua0-x243.google.com ([2607:f8b0:400c:c08::243]:37337) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dm9JC-0001FH-Ng for qemu-devel@nongnu.org; Sun, 27 Aug 2017 21:57:46 -0400 Received: by mail-ua0-x243.google.com with SMTP id 104so848971uas.4 for ; Sun, 27 Aug 2017 18:57:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=qM+YCzUmM1npnKwHgvb6aUdqLdaBqZaMnfRuqHsM17o=; b=PDZWo8XdHFyM6OcwZBpu4NtkVws0ByqocWFdWJVy1etfuLiGvYnJM/CIK1KX9w2ORi PmXnE7nJQJcKavxvQMmlFvguE5x4MQnYMcbcCEhMiyEiUk8eKpFgcCrlHyyL+mjntvRp Bwz4/RO7s7BLjj02u8YRC4jW5t4k55SaeK3IX5F6bDkq2042eF6+vz0jSeopblM28k+1 HAUb9NHPqMuhFkbk3MyDTtL5x1nykxuuX21WWJE6t+oRNl7RPCXddXAzfTeke3CRpi40 W84hb1rqU0X4m3gVbykMroJYf1VNueK3YvUufJED7ZvKH2qqvzls8jmgOhB3cx4heIiY ZtWg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=qM+YCzUmM1npnKwHgvb6aUdqLdaBqZaMnfRuqHsM17o=; b=peJMA71Kfg/u8m854TNxPKVSZEGL2E7mejKLg7LlLWm6XZrABzgQGgthbtWUkQwMzZ YzftOc68kqdAbpvq0knhWJ689ZR6hohUMNxOO0O3XFWShEB1Zt8U2CCuW+HBVj7KP9Cx HCq34DwFNvEISIOUZQPm96gxJHDqjteZtC+p+7E2scjGJgBMn5OifP03zK6Kyon5LwqR 7q09NX5e2ddKO4G3a++sln3MCyR5hgsuM5Sm6V0guy30+xgnpnNHeKxMKZhi00yBe3iC Y1nN0159hQ2Pgrpgytr9iFUV735r3W2O8S1ukej4tUC8Q6dU7A4nkuOObu5Kim1hIFnp 2f9A== X-Gm-Message-State: AHYfb5i4QgZuqQq+TCX/LhHTwYBZeFvZCqnE6/cil3e5bmMymoPJoRhG /YGTgkbel/dZM3ib X-Received: by 10.159.33.97 with SMTP id 88mr3667280uab.5.1503885465939; Sun, 27 Aug 2017 18:57:45 -0700 (PDT) Received: from localhost.localdomain ([191.109.6.191]) by smtp.gmail.com with ESMTPSA id y12sm2696824uad.22.2017.08.27.18.57.44 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 27 Aug 2017 18:57:45 -0700 (PDT) From: Sergio Andres Gomez Del Real X-Google-Original-From: Sergio Andres Gomez Del Real To: qemu-devel@nongnu.org Date: Sun, 27 Aug 2017 20:56:51 -0500 Message-Id: <20170828015654.2530-12-Sergio.G.DelReal@gmail.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170828015654.2530-1-Sergio.G.DelReal@gmail.com> References: <20170828015654.2530-1-Sergio.G.DelReal@gmail.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400c:c08::243 Subject: [Qemu-devel] [PATCH 11/14] hvf: implement vga dirty page tracking X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Sergio Andres Gomez Del Real Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP This commit implements setting the tracking of dirty pages, using hvf's interface to protect guest memory. It uses the MemoryListener callback mechanism through .log_start/stop/sync Signed-off-by: Sergio Andres Gomez Del Real --- include/sysemu/hvf.h | 5 ++++ target/i386/hvf-all.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 70 insertions(+), 7 deletions(-) diff --git a/include/sysemu/hvf.h b/include/sysemu/hvf.h index 5b92769b16..90e9ec174e 100644 --- a/include/sysemu/hvf.h +++ b/include/sysemu/hvf.h @@ -27,11 +27,16 @@ #include #endif +/* hvf_slot flags */ +#define HVF_SLOT_LOG (1 << 0) + typedef struct hvf_slot { uint64_t start; uint64_t size; uint8_t *mem; int slot_id; + uint32_t flags; + MemoryRegion *region; } hvf_slot; struct hvf_vcpu_caps { diff --git a/target/i386/hvf-all.c b/target/i386/hvf-all.c index 11d20671f7..20c796089d 100644 --- a/target/i386/hvf-all.c +++ b/target/i386/hvf-all.c @@ -172,6 +172,7 @@ void hvf_set_phys_mem(MemoryRegionSection *section, bool add) mem->size = int128_get64(section->size); mem->mem = memory_region_get_ram_ptr(area) + section->offset_within_region; mem->start = section->offset_within_address_space; + mem->region = area; if (do_hvf_set_memory(mem)) { fprintf(stderr, "Error registering new memory slot\n"); @@ -441,8 +442,7 @@ void hvf_cpu_synchronize_post_init(CPUState *cpu_state) run_on_cpu(cpu_state, _hvf_cpu_synchronize_post_init, RUN_ON_CPU_NULL); } -/* TODO: ept fault handlig */ -static bool ept_emulation_fault(uint64_t ept_qual) +static bool ept_emulation_fault(hvf_slot *slot, addr_t gpa, uint64_t ept_qual) { int read, write; @@ -458,6 +458,14 @@ static bool ept_emulation_fault(uint64_t ept_qual) return false; } + if (write && slot) { + if (slot->flags & HVF_SLOT_LOG) { + memory_region_set_dirty(slot->region, gpa - slot->start, 1); + hv_vm_protect((hv_gpaddr_t)slot->start, (size_t)slot->size, + HV_MEMORY_READ | HV_MEMORY_WRITE); + } + } + /* * The EPT violation must have been caused by accessing a * guest-physical address that is a translation of a guest-linear @@ -468,7 +476,57 @@ static bool ept_emulation_fault(uint64_t ept_qual) return false; } - return true; + return !slot; +} + +static void hvf_set_dirty_tracking(MemoryRegionSection *section, bool on) +{ + struct mac_slot *macslot; + hvf_slot *slot; + + slot = hvf_find_overlap_slot( + section->offset_within_address_space, + section->offset_within_address_space + int128_get64(section->size)); + + /* protect region against writes; begin tracking it */ + if (on) { + slot->flags |= HVF_SLOT_LOG; + hv_vm_protect((hv_gpaddr_t)slot->start, (size_t)slot->size, + HV_MEMORY_READ); + /* stop tracking region*/ + } else { + slot->flags &= ~HVF_SLOT_LOG; + hv_vm_protect((hv_gpaddr_t)slot->start, (size_t)slot->size, + HV_MEMORY_READ | HV_MEMORY_WRITE); + } +} + +static void hvf_log_start(MemoryListener *listener, + MemoryRegionSection *section, int old, int new) +{ + if (old != 0) + return; + + hvf_set_dirty_tracking(section, 1); +} + +static void hvf_log_stop(MemoryListener *listener, + MemoryRegionSection *section, int old, int new) +{ + if (new != 0) + return; + + hvf_set_dirty_tracking(section, 0); +} + +static void hvf_log_sync(MemoryListener *listener, + MemoryRegionSection *section) +{ + /* + * sync of dirty pages is handled elsewhere; just make sure we keep + * tracking the region. + */ + hvf_set_dirty_tracking(section, 1); } static void hvf_region_add(MemoryListener *listener, @@ -487,6 +545,9 @@ static MemoryListener hvf_memory_listener = { .priority = 10, .region_add = hvf_region_add, .region_del = hvf_region_del, + .log_start = hvf_log_start, + .log_stop = hvf_log_stop, + .log_sync = hvf_log_sync, }; void vmx_reset_vcpu(CPUState *cpu) { @@ -763,7 +824,7 @@ int hvf_vcpu_exec(CPUState *cpu) slot = hvf_find_overlap_slot(gpa, gpa); /* mmio */ - if (ept_emulation_fault(exit_qual) && !slot) { + if (ept_emulation_fault(slot, gpa, exit_qual)) { struct x86_decode decode; load_regs(cpu); @@ -774,9 +835,6 @@ int hvf_vcpu_exec(CPUState *cpu) store_regs(cpu); break; } -#ifdef DIRTY_VGA_TRACKING - /* TODO: handle dirty page tracking */ -#endif break; } case EXIT_REASON_INOUT: