From patchwork Mon Jan 4 19:49:04 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Michael S. Tsirkin" X-Patchwork-Id: 42212 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 0672FB6EED for ; Wed, 6 Jan 2010 09:38:23 +1100 (EST) Received: from localhost ([127.0.0.1]:53994 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NSI2d-0007tT-4k for incoming@patchwork.ozlabs.org; Tue, 05 Jan 2010 17:38:19 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NSFYM-0004Ax-84 for qemu-devel@nongnu.org; Tue, 05 Jan 2010 14:58:54 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1NSFYH-00047y-Er for qemu-devel@nongnu.org; Tue, 05 Jan 2010 14:58:53 -0500 Received: from [199.232.76.173] (port=43304 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NSFYH-00047t-Ac for qemu-devel@nongnu.org; Tue, 05 Jan 2010 14:58:49 -0500 Received: from mx20.gnu.org ([199.232.41.8]:36430) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1NSFYG-0005CH-Ho for qemu-devel@nongnu.org; Tue, 05 Jan 2010 14:58:48 -0500 Received: from mx1.redhat.com ([209.132.183.28]) by mx20.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1NRsyE-0004Qg-Op for qemu-devel@nongnu.org; Mon, 04 Jan 2010 14:52:07 -0500 Received: from int-mx04.intmail.prod.int.phx2.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.17]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o04JpvFC021995 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 4 Jan 2010 14:51:57 -0500 Received: from redhat.com (vpn1-7-102.ams2.redhat.com [10.36.7.102]) by int-mx04.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id o04JpsC5016244; Mon, 4 Jan 2010 14:51:55 -0500 Date: Mon, 4 Jan 2010 21:49:04 +0200 From: "Michael S. Tsirkin" To: Anthony Liguori , qemu-devel@nongnu.org, avi@redhat.com, gleb@redhat.com Message-ID: <20100104194904.GB21299@redhat.com> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.19 (2009-01-05) X-Scanned-By: MIMEDefang 2.67 on 10.5.11.17 X-detected-operating-system: by mx20.gnu.org: Genre and OS details not recognized. X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) Cc: Subject: [Qemu-devel] [PATCHv2 1/3] qemu: memory notifiers X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org This adds notifiers for phys memory changes: a set of callbacks that vhost can register and update kernel accordingly. Down the road, kvm code can be switched to use these as well, instead of calling kvm code directly from exec.c as is done now. Signed-off-by: Michael S. Tsirkin --- cpu-common.h | 19 ++++++++++ exec.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 127 insertions(+), 3 deletions(-) diff --git a/cpu-common.h b/cpu-common.h index 6302372..0ec9b72 100644 --- a/cpu-common.h +++ b/cpu-common.h @@ -8,6 +8,7 @@ #endif #include "bswap.h" +#include "qemu-queue.h" /* address in the RAM (different from a physical address) */ typedef unsigned long ram_addr_t; @@ -61,6 +62,24 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len, void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque)); void cpu_unregister_map_client(void *cookie); +struct CPUPhysMemoryClient; +typedef struct CPUPhysMemoryClient CPUPhysMemoryClient; +struct CPUPhysMemoryClient { + void (*set_memory)(struct CPUPhysMemoryClient *client, + target_phys_addr_t start_addr, + ram_addr_t size, + ram_addr_t phys_offset); + int (*sync_dirty_bitmap)(struct CPUPhysMemoryClient *client, + target_phys_addr_t start_addr, + target_phys_addr_t end_addr); + int (*migration_log)(struct CPUPhysMemoryClient *client, + int enable); + QLIST_ENTRY(CPUPhysMemoryClient) list; +}; + +void cpu_register_phys_memory_client(CPUPhysMemoryClient *); +void cpu_unregister_phys_memory_client(CPUPhysMemoryClient *); + uint32_t ldub_phys(target_phys_addr_t addr); uint32_t lduw_phys(target_phys_addr_t addr); uint32_t ldl_phys(target_phys_addr_t addr); diff --git a/exec.c b/exec.c index 1190591..56c347b 100644 --- a/exec.c +++ b/exec.c @@ -1623,6 +1623,99 @@ const CPULogItem cpu_log_items[] = { { 0, NULL, NULL }, }; +static QLIST_HEAD(memory_client_list, CPUPhysMemoryClient) memory_client_list + = QLIST_HEAD_INITIALIZER(memory_client_list); + +static void cpu_notify_set_memory(target_phys_addr_t start_addr, + ram_addr_t size, + ram_addr_t phys_offset) +{ + CPUPhysMemoryClient *client; + QLIST_FOREACH(client, &memory_client_list, list) { + client->set_memory(client, start_addr, size, phys_offset); + } +} + +static int cpu_notify_sync_dirty_bitmap(target_phys_addr_t start, + target_phys_addr_t end) +{ + CPUPhysMemoryClient *client; + QLIST_FOREACH(client, &memory_client_list, list) { + int r = client->sync_dirty_bitmap(client, start, end); + if (r < 0) + return r; + } + return 0; +} + +static int cpu_notify_migration_log(int enable) +{ + CPUPhysMemoryClient *client; + QLIST_FOREACH(client, &memory_client_list, list) { + int r = client->migration_log(client, enable); + if (r < 0) + return r; + } + return 0; +} + +static void phys_page_for_each_in_l1_map(PhysPageDesc **phys_map, + CPUPhysMemoryClient *client) +{ + PhysPageDesc *pd; + int l1, l2; + + for (l1 = 0; l1 < L1_SIZE; ++l1) { + pd = phys_map[l1]; + if (!pd) { + continue; + } + for (l2 = 0; l2 < L2_SIZE; ++l2) { + if (pd[l2].phys_offset == IO_MEM_UNASSIGNED) { + continue; + } + client->set_memory(client, pd[l2].region_offset, + TARGET_PAGE_SIZE, pd[l2].phys_offset); + } + } +} + +static void phys_page_for_each(CPUPhysMemoryClient *client) +{ +#if TARGET_PHYS_ADDR_SPACE_BITS > 32 + +#if TARGET_PHYS_ADDR_SPACE_BITS > (32 + L1_BITS) +#error unsupported TARGET_PHYS_ADDR_SPACE_BITS +#endif + void **phys_map = (void **)l1_phys_map; + int l1; + if (!l1_phys_map) { + return; + } + for (l1 = 0; l1 < L1_SIZE; ++l1) { + if (phys_map[l1]) { + phys_page_for_each_in_l1_map(phys_map[l1], client); + } + } +#else + if (!l1_phys_map) { + return; + } + phys_page_for_each_in_l1_map(l1_phys_map, client); +#endif +} + +void cpu_register_phys_memory_client(CPUPhysMemoryClient *client) +{ + QLIST_INSERT_HEAD(&memory_client_list, client, list); + phys_page_for_each(client); +} + +void cpu_unregister_phys_memory_client(CPUPhysMemoryClient *client) +{ + QLIST_REMOVE(client, list); +} + static int cmp1(const char *s1, int n, const char *s2) { if (strlen(s2) != n) @@ -1882,11 +1975,16 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end, int cpu_physical_memory_set_dirty_tracking(int enable) { + int ret = 0; in_migration = enable; if (kvm_enabled()) { - return kvm_set_migration_log(enable); + ret = kvm_set_migration_log(enable); } - return 0; + if (ret < 0) { + return ret; + } + ret = cpu_notify_migration_log(!!enable); + return ret; } int cpu_physical_memory_get_dirty_tracking(void) @@ -1899,8 +1997,13 @@ int cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, { int ret = 0; - if (kvm_enabled()) + if (kvm_enabled()) { ret = kvm_physical_sync_dirty_bitmap(start_addr, end_addr); + } + if (ret < 0) { + return ret; + } + ret = cpu_notify_sync_dirty_bitmap(start_addr, end_addr); return ret; } @@ -2315,6 +2418,8 @@ void cpu_register_physical_memory_offset(target_phys_addr_t start_addr, if (kvm_enabled()) kvm_set_phys_mem(start_addr, size, phys_offset); + cpu_notify_set_memory(start_addr, size, phys_offset); + if (phys_offset == IO_MEM_UNASSIGNED) { region_offset = start_addr; }