From patchwork Thu Mar 31 17:43:29 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Michael S. Tsirkin" X-Patchwork-Id: 89102 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 233D1B6EF0 for ; Fri, 1 Apr 2011 04:44:42 +1100 (EST) Received: from localhost ([127.0.0.1]:49137 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Q5LvC-00010I-LP for incoming@patchwork.ozlabs.org; Thu, 31 Mar 2011 13:44:38 -0400 Received: from [140.186.70.92] (port=46660 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Q5LuV-0000zo-Sp for qemu-devel@nongnu.org; Thu, 31 Mar 2011 13:43:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Q5LuQ-0003LB-Tr for qemu-devel@nongnu.org; Thu, 31 Mar 2011 13:43:55 -0400 Received: from mx1.redhat.com ([209.132.183.28]:52431) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Q5LuQ-0003Kj-CQ for qemu-devel@nongnu.org; Thu, 31 Mar 2011 13:43:50 -0400 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.14.4/8.14.4) with ESMTP id p2VHhmiN007240 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Thu, 31 Mar 2011 13:43:48 -0400 Received: from redhat.com (vpn-200-93.tlv.redhat.com [10.35.200.93]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with SMTP id p2VHhjbj029800 for ; Thu, 31 Mar 2011 13:43:46 -0400 Date: Thu, 31 Mar 2011 19:43:29 +0200 From: "Michael S. Tsirkin" To: qemu-devel@nongnu.org Message-ID: <20110331174328.GA25133@redhat.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH RFC] vga: flag vga ram for 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 Currently, vga cards that allocate vga ram, register it as regular ram. When this happens a lot, vhost need to get notified and flush its memory tables, which is slow. This was observed with cirrus vga. As a solution, add an explicit flag when registering vga ram, vhost-net can simply ignore it. Long term, we might be able to use this API to avoid the need to request dirty loggin from devices explicitly. Tested: with cirrus vga only. Signed-off-by: Michael S. Tsirkin --- cpu-common.h | 22 +++++++++++++++++----- exec.c | 14 ++++++++------ hw/cirrus_vga.c | 34 ++++++++++++++++++++++------------ hw/g364fb.c | 2 +- hw/vga-isa-mm.c | 4 ++-- hw/vga-pci.c | 3 ++- hw/vga.c | 4 ++-- hw/vhost.c | 7 ++++++- 8 files changed, 60 insertions(+), 30 deletions(-) diff --git a/cpu-common.h b/cpu-common.h index acb91ac..e0477e9 100644 --- a/cpu-common.h +++ b/cpu-common.h @@ -18,10 +18,21 @@ typedef unsigned long ram_addr_t; typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t addr, uint32_t value); typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr); -void cpu_register_physical_memory_offset(target_phys_addr_t start_addr, - ram_addr_t size, - ram_addr_t phys_offset, - ram_addr_t region_offset); +void cpu_register_physical_memory_vga(target_phys_addr_t start_addr, + ram_addr_t size, + ram_addr_t phys_offset, + ram_addr_t region_offset, + bool vga_ram); + +static inline void cpu_register_physical_memory_offset(target_phys_addr_t start_addr, + ram_addr_t size, + ram_addr_t phys_offset, + ram_addr_t region_offset) +{ + cpu_register_physical_memory_vga(start_addr, size, phys_offset, + region_offset, false); +} + static inline void cpu_register_physical_memory(target_phys_addr_t start_addr, ram_addr_t size, ram_addr_t phys_offset) @@ -69,7 +80,8 @@ struct CPUPhysMemoryClient { void (*set_memory)(struct CPUPhysMemoryClient *client, target_phys_addr_t start_addr, ram_addr_t size, - ram_addr_t phys_offset); + ram_addr_t phys_offset, + bool vga_ram); int (*sync_dirty_bitmap)(struct CPUPhysMemoryClient *client, target_phys_addr_t start_addr, target_phys_addr_t end_addr); diff --git a/exec.c b/exec.c index b992016..6435378 100644 --- a/exec.c +++ b/exec.c @@ -1635,11 +1635,12 @@ static QLIST_HEAD(memory_client_list, CPUPhysMemoryClient) memory_client_list static void cpu_notify_set_memory(target_phys_addr_t start_addr, ram_addr_t size, - ram_addr_t phys_offset) + ram_addr_t phys_offset, + bool vga_ram) { CPUPhysMemoryClient *client; QLIST_FOREACH(client, &memory_client_list, list) { - client->set_memory(client, start_addr, size, phys_offset); + client->set_memory(client, start_addr, size, phys_offset, vga_ram); } } @@ -1682,7 +1683,7 @@ static void phys_page_for_each_in_l1_map(PhysPageDesc **phys_map, continue; } client->set_memory(client, pd[l2].region_offset, - TARGET_PAGE_SIZE, pd[l2].phys_offset); + TARGET_PAGE_SIZE, pd[l2].phys_offset, false); } } } @@ -2418,10 +2419,11 @@ static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys, start_addr and region_offset are rounded down to a page boundary before calculating this offset. This should not be a problem unless the low bits of start_addr and region_offset differ. */ -void cpu_register_physical_memory_offset(target_phys_addr_t start_addr, +void cpu_register_physical_memory_vga(target_phys_addr_t start_addr, ram_addr_t size, ram_addr_t phys_offset, - ram_addr_t region_offset) + ram_addr_t region_offset, + bool vga_ram) { target_phys_addr_t addr, end_addr; PhysPageDesc *p; @@ -2432,7 +2434,7 @@ 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); + cpu_notify_set_memory(start_addr, size, phys_offset, vga_ram); if (phys_offset == IO_MEM_UNASSIGNED) { region_offset = start_addr; diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c index d04adeb..435d914 100644 --- a/hw/cirrus_vga.c +++ b/hw/cirrus_vga.c @@ -2557,7 +2557,9 @@ static void map_linear_vram(CirrusVGAState *s) if (!s->vga.map_addr && s->vga.lfb_addr && s->vga.lfb_end) { s->vga.map_addr = s->vga.lfb_addr; s->vga.map_end = s->vga.lfb_end; - cpu_register_physical_memory(s->vga.map_addr, s->vga.map_end - s->vga.map_addr, s->vga.vram_offset); + cpu_register_physical_memory_vga(s->vga.map_addr, + s->vga.map_end - s->vga.map_addr, + s->vga.vram_offset, 0, true); } if (!s->vga.map_addr) @@ -2566,26 +2568,34 @@ static void map_linear_vram(CirrusVGAState *s) #ifndef TARGET_IA64 s->vga.lfb_vram_mapped = 0; - cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x8000, - (s->vga.vram_offset + s->cirrus_bank_base[0]) | IO_MEM_UNASSIGNED); - cpu_register_physical_memory(isa_mem_base + 0xa8000, 0x8000, - (s->vga.vram_offset + s->cirrus_bank_base[1]) | IO_MEM_UNASSIGNED); + cpu_register_physical_memory_vga(isa_mem_base + 0xa0000, 0x8000, + (s->vga.vram_offset + + s->cirrus_bank_base[0]) | + IO_MEM_UNASSIGNED, 0, true); + cpu_register_physical_memory_vga(isa_mem_base + 0xa8000, 0x8000, + (s->vga.vram_offset + + s->cirrus_bank_base[1]) | + IO_MEM_UNASSIGNED, 0, true); if (!(s->cirrus_srcptr != s->cirrus_srcptr_end) && !((s->vga.sr[0x07] & 0x01) == 0) && !((s->vga.gr[0x0B] & 0x14) == 0x14) && !(s->vga.gr[0x0B] & 0x02)) { vga_dirty_vga_stop(&s->vga); - cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x8000, - (s->vga.vram_offset + s->cirrus_bank_base[0]) | IO_MEM_RAM); - cpu_register_physical_memory(isa_mem_base + 0xa8000, 0x8000, - (s->vga.vram_offset + s->cirrus_bank_base[1]) | IO_MEM_RAM); + cpu_register_physical_memory_vga(isa_mem_base + 0xa0000, 0x8000, + (s->vga.vram_offset + + s->cirrus_bank_base[0]) | + IO_MEM_RAM, 0, true); + cpu_register_physical_memory_vga(isa_mem_base + 0xa8000, 0x8000, + (s->vga.vram_offset + + s->cirrus_bank_base[1]) | + IO_MEM_RAM, 0, true); s->vga.lfb_vram_mapped = 1; } else { cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x20000, s->vga.vga_io_memory); } #endif diff --git a/hw/g364fb.c b/hw/g364fb.c index 3c8fb98..3734902 100644 --- a/hw/g364fb.c +++ b/hw/g364fb.c @@ -605,7 +605,7 @@ int g364fb_mm_init(target_phys_addr_t vram_base, g364fb_invalidate_display, g364fb_screen_dump, NULL, s); - cpu_register_physical_memory(vram_base, s->vram_size, s->vram_offset); + cpu_register_physical_memory_vga(vram_base, s->vram_size, s->vram_offset, 0, true); io_ctrl = cpu_register_io_memory(g364fb_ctrl_read, g364fb_ctrl_write, s); cpu_register_physical_memory(ctrl_base, 0x200000, io_ctrl); diff --git a/hw/vga-isa-mm.c b/hw/vga-isa-mm.c index b4ff23c..500507d 100644 --- a/hw/vga-isa-mm.c +++ b/hw/vga-isa-mm.c @@ -123,8 +123,8 @@ int isa_vga_mm_init(target_phys_addr_t vram_base, #ifdef CONFIG_BOCHS_VBE /* XXX: use optimized standard vga accesses */ - cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS, - VGA_RAM_SIZE, s->vga.vram_offset); + cpu_register_physical_memory_vga(VBE_DISPI_LFB_PHYSICAL_ADDRESS, + VGA_RAM_SIZE, s->vga.vram_offset, 0, true); #endif return 0; } diff --git a/hw/vga-pci.c b/hw/vga-pci.c index f6fb1b3..3a673cf 100644 --- a/hw/vga-pci.c +++ b/hw/vga-pci.c @@ -55,7 +55,8 @@ static void vga_map(PCIDevice *pci_dev, int region_num, if (region_num == PCI_ROM_SLOT) { cpu_register_physical_memory(addr, s->bios_size, s->bios_offset); } else { - cpu_register_physical_memory(addr, s->vram_size, s->vram_offset); + cpu_register_physical_memory_vga(addr, s->vram_size, s->vram_offset, 0, + true); s->map_addr = addr; s->map_end = addr + s->vram_size; vga_dirty_vga_start(s); diff --git a/hw/vga.c b/hw/vga.c index 1d269d5..a742dd4 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -2359,8 +2359,8 @@ void vga_init_vbe(VGACommonState *s) { #ifdef CONFIG_BOCHS_VBE /* XXX: use optimized standard vga accesses */ - cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS, - VGA_RAM_SIZE, s->vram_offset); + cpu_register_physical_memory_vga(VBE_DISPI_LFB_PHYSICAL_ADDRESS, + VGA_RAM_SIZE, s->vram_offset,0 , true); s->vbe_mapped = 1; #endif } diff --git a/hw/vhost.c b/hw/vhost.c index 8e28fd9..27d08c0 100644 --- a/hw/vhost.c +++ b/hw/vhost.c @@ -379,7 +379,8 @@ static bool vhost_dev_cmp_memory(struct vhost_dev *dev, static void vhost_client_set_memory(CPUPhysMemoryClient *client, target_phys_addr_t start_addr, ram_addr_t size, - ram_addr_t phys_offset) + ram_addr_t phys_offset, + bool vga_ram) { struct vhost_dev *dev = container_of(client, struct vhost_dev, client); ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK; @@ -388,6 +389,10 @@ static void vhost_client_set_memory(CPUPhysMemoryClient *client, uint64_t log_size; int r; + if (vga_ram) { + flags = IO_MEM_UNASSIGNED; + } + /* Optimize no-change case. At least cirrus_vga does this a lot at this time. */ if (flags == IO_MEM_RAM) { if (!vhost_dev_cmp_memory(dev, start_addr, size,