From patchwork Thu Feb 4 15:27:19 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: 77030 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o14FUrsx015920 for ; Thu, 4 Feb 2010 15:30:54 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932751Ab0BDPac (ORCPT ); Thu, 4 Feb 2010 10:30:32 -0500 Received: from mx1.redhat.com ([209.132.183.28]:6808 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932744Ab0BDPaa (ORCPT ); Thu, 4 Feb 2010 10:30:30 -0500 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o14FUUXw004680 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Thu, 4 Feb 2010 10:30:30 -0500 Received: from redhat.com (vpn2-9-138.ams2.redhat.com [10.36.9.138]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id o14FUS30022733 for ; Thu, 4 Feb 2010 10:30:29 -0500 Date: Thu, 4 Feb 2010 17:27:19 +0200 From: "Michael S. Tsirkin" To: kvm@vger.kernel.org Subject: [PATCH 01/20] exec: memory notifiers Message-ID: <20100204152719.GB8461@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.11 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Thu, 04 Feb 2010 15:30:54 +0000 (UTC) diff --git a/cpu-common.h b/cpu-common.h index 5e59564..326513d 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; @@ -62,6 +63,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 ade09cb..fb3ce3f 100644 --- a/exec.c +++ b/exec.c @@ -1642,6 +1642,101 @@ const CPULogItem cpu_log_items[] = { { 0, NULL, NULL }, }; +#ifndef CONFIG_USER_ONLY +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); +} +#endif + static int cmp1(const char *s1, int n, const char *s2) { if (strlen(s2) != n) @@ -1901,10 +1996,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) @@ -1917,8 +2018,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; } @@ -2333,6 +2439,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; }