From nobody Wed Nov 27 08:48:09 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1699979559; cv=none; d=zohomail.com; s=zohoarc; b=nacet/NAcrgSTss9XenDAdWMTB6y8WwU3ZzFUO7Es8MLH2yLzfuV1RVc98JQq447EWRWDHkLkCnl4+wLX2M0nfJpSy1eUtTqEvO2LrQfBnTiMXgABrdDTMxFrfLlSnENAFvXrer/5fYPguerhlyDD9/3B3he71o7CwiU0h8cKdY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1699979559; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=fBoLjADQF92oUz8YGjrCFJ5vAIgrltjc0XkKGW8dGlc=; b=K9vOdqoDf6o28looEb9x7U34LRCEy+9lvzN98qVT9uupDHR/uNJ0Y3Tv+afASyIReauKzW9tYCX/N6kMIrVkHflKMkfjRtH0iQviMpWspRv8DDsAIvF3XzEJ5/0WnS798+Bo0jJkKVQpBB73k9yrjtCjZcIN6y8/hAod0xG3YDo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1699979559204284.66083570797196; Tue, 14 Nov 2023 08:32:39 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.632947.987512 (Exim 4.92) (envelope-from ) id 1r2wKq-000623-VW; Tue, 14 Nov 2023 16:32:20 +0000 Received: by outflank-mailman (output) from mailman id 632947.987512; Tue, 14 Nov 2023 16:32:20 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1r2wKq-00061u-RT; Tue, 14 Nov 2023 16:32:20 +0000 Received: by outflank-mailman (input) for mailman id 632947; Tue, 14 Nov 2023 16:32:19 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1r2wKp-0002h9-Ly for xen-devel@lists.xenproject.org; Tue, 14 Nov 2023 16:32:19 +0000 Received: from mail-ej1-x632.google.com (mail-ej1-x632.google.com [2a00:1450:4864:20::632]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 5fdbd3cf-830b-11ee-9b0e-b553b5be7939; Tue, 14 Nov 2023 17:32:17 +0100 (CET) Received: by mail-ej1-x632.google.com with SMTP id a640c23a62f3a-9d0b4dfd60dso875144566b.1 for ; Tue, 14 Nov 2023 08:32:17 -0800 (PST) Received: from m1x-phil.lan (cac94-h02-176-184-25-155.dsl.sta.abo.bbox.fr. [176.184.25.155]) by smtp.gmail.com with ESMTPSA id s12-20020a1709066c8c00b0099cd008c1a4sm5788138ejr.136.2023.11.14.08.32.14 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Tue, 14 Nov 2023 08:32:16 -0800 (PST) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 5fdbd3cf-830b-11ee-9b0e-b553b5be7939 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1699979537; x=1700584337; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=fBoLjADQF92oUz8YGjrCFJ5vAIgrltjc0XkKGW8dGlc=; b=YGlkzW7+UUuHZbgWRszP1Okvh2X3JotR5IEHlRam07sMXB3o9NVe/IWN4o9BwGvcso 9QzdCoiWw26rNv3cXt6B5bPr9jv5Sci1l2FGHl6gMq8reQWoGjNNHvFYMyCzYg5JXsfp EIzRWEPZeKH7dQxzkEMZ7kUR0RWvVK9ztRAVmCG9kPmfpTY6CC4ZZwMq4vR2GFr/hshT 9ZUrhkDhG8u5vnLVm+LHuo/vcJLO4STYLgAO9dOM6OQmglEKLiOW8BOkJc1kpw+hJaVz nLWlZIK4FZt8TEuARf7HjUwq3ln3sDdRa56mOg1JZYR61Nh8A3SgISuNxrS8QXtXdIHc vYww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699979537; x=1700584337; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=fBoLjADQF92oUz8YGjrCFJ5vAIgrltjc0XkKGW8dGlc=; b=rjZYHQz1ZvgHLRBLFAzR49/qj8bftz9KjSy43mYutf03W8qwL4uN1kG92zoBDcxCsv gVtSLJd47ha9/wFeyqwRaDBzHHxYBOHTNICUWzZUwcUBuDX3ubImVn5XE8BJXbO+uaEl j3KLdkRI4unPted5D+b30ge/l+yes5Fnp+F+YEUYliOshSa/lnVZzYj1FHP0NM6/1QFc ecDKhyG0j2+egxrSS7rAJv34YV4nMuPunMYGuPOMNmcavBE+IWT5mE4l1DMp2ddHnm5G anqWXSQYe9ws9LkYVcyFa0XQcwdNwsZ9u5OuTNxK6zcha0AF//MIjoKY2BEBxiJty4AY Bq+w== X-Gm-Message-State: AOJu0YxTFRE9ycyMDzNn/hHqu4spqYR6nduTbW++DPkt6k+w12r48OVP HsIePbmjptca9k2S0SF6sY0W2A== X-Google-Smtp-Source: AGHT+IHCzaPi5Ki96YFTxblFzU9hUvvVJMXhVG8xP2TJoi7bkBVxcUKkybZuFBTY+HQf7VLJRu7P5A== X-Received: by 2002:a17:906:dc9:b0:9d4:84b6:8709 with SMTP id p9-20020a1709060dc900b009d484b68709mr6908245eji.58.1699979536701; Tue, 14 Nov 2023 08:32:16 -0800 (PST) From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= To: qemu-devel@nongnu.org Cc: Anthony Perard , Paul Durrant , David Woodhouse , Thomas Huth , qemu-arm@nongnu.org, Stefano Stabellini , Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , xen-devel@lists.xenproject.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Peter Maydell , "Michael S. Tsirkin" , Marcel Apfelbaum , Richard Henderson , Eduardo Habkost Subject: [RFC PATCH-for-9.0 8/9] hw/xen/hvm: Merge xen-hvm-common.c files Date: Tue, 14 Nov 2023 17:31:22 +0100 Message-ID: <20231114163123.74888-9-philmd@linaro.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20231114163123.74888-1-philmd@linaro.org> References: <20231114163123.74888-1-philmd@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @linaro.org) X-ZM-MESSAGEID: 1699979560798100001 hw/i386/xen/xen-hvm-common.c content is target agnostic, and should be common to all targets. Merge both files. Remove the now unnecessary xen_register_framebuffer() stub. ARM targets now inherit the common xen_memory_listener. Signed-off-by: Philippe Mathieu-Daud=C3=A9 --- hw/arm/xen_arm.c | 24 -- hw/i386/xen/xen-hvm-common.c | 473 ----------------------------------- hw/xen/xen-hvm-common.c | 458 +++++++++++++++++++++++++++++++++ stubs/xen-hw-stub.c | 4 - hw/i386/xen/meson.build | 1 - 5 files changed, 458 insertions(+), 502 deletions(-) delete mode 100644 hw/i386/xen/xen-hvm-common.c diff --git a/hw/arm/xen_arm.c b/hw/arm/xen_arm.c index 39dcd74d07..0ead84c9e1 100644 --- a/hw/arm/xen_arm.c +++ b/hw/arm/xen_arm.c @@ -38,17 +38,6 @@ #define TYPE_XEN_ARM MACHINE_TYPE_NAME("xenpvh") OBJECT_DECLARE_SIMPLE_TYPE(XenArmState, XEN_ARM) =20 -const MemoryListener xen_memory_listener =3D { - .region_add =3D xen_region_add, - .region_del =3D xen_region_del, - .log_start =3D NULL, - .log_stop =3D NULL, - .log_sync =3D NULL, - .log_global_start =3D NULL, - .log_global_stop =3D NULL, - .priority =3D MEMORY_LISTENER_PRIORITY_ACCEL, -}; - struct XenArmState { /*< private >*/ MachineState parent; @@ -136,19 +125,6 @@ void xen_arch_handle_ioreq(XenIOState *state, ioreq_t = *req) return; } =20 -void xen_arch_set_memory(XenIOState *state, MemoryRegionSection *section, - bool add) -{ -} - -void xen_hvm_modified_memory(ram_addr_t start, ram_addr_t length) -{ -} - -void qmp_xen_set_global_dirty_log(bool enable, Error **errp) -{ -} - #ifdef CONFIG_TPM static void xen_enable_tpm(XenArmState *xam) { diff --git a/hw/i386/xen/xen-hvm-common.c b/hw/i386/xen/xen-hvm-common.c deleted file mode 100644 index e8ef0e0c94..0000000000 --- a/hw/i386/xen/xen-hvm-common.c +++ /dev/null @@ -1,473 +0,0 @@ -/* - * Copyright (C) 2010 Citrix Ltd. - * - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. - * - * Contributions after 2012-01-13 are licensed under the terms of the - * GNU GPL, version 2 or (at your option) any later version. - */ - -#include "qemu/osdep.h" -#include "qemu/range.h" -#include "qapi/qapi-commands-migration.h" -#include "exec/target_page.h" -#include "hw/xen/xen-hvm-common.h" -#include "trace.h" - -static MemoryRegion *framebuffer; -static bool xen_in_migration; - -static QLIST_HEAD(, XenPhysmap) xen_physmap; -static const XenPhysmap *log_for_dirtybit; -/* Buffer used by xen_sync_dirty_bitmap */ -static unsigned long *dirty_bitmap; - -static XenPhysmap *get_physmapping(hwaddr start_addr, ram_addr_t size, - int page_mask) -{ - XenPhysmap *physmap =3D NULL; - - start_addr &=3D -page_mask; - - QLIST_FOREACH(physmap, &xen_physmap, list) { - if (range_covers_byte(physmap->start_addr, physmap->size, start_ad= dr)) { - return physmap; - } - } - return NULL; -} - -static hwaddr xen_phys_offset_to_gaddr(hwaddr phys_offset, ram_addr_t size, - int page_mask) -{ - hwaddr addr =3D phys_offset & -page_mask; - XenPhysmap *physmap =3D NULL; - - QLIST_FOREACH(physmap, &xen_physmap, list) { - if (range_covers_byte(physmap->phys_offset, physmap->size, addr)) { - return physmap->start_addr + (phys_offset - physmap->phys_offs= et); - } - } - - return phys_offset; -} - -#ifdef XEN_COMPAT_PHYSMAP -static int xen_save_physmap(XenIOState *state, XenPhysmap *physmap) -{ - char path[80], value[17]; - - snprintf(path, sizeof(path), - "/local/domain/0/device-model/%d/physmap/%"PRIx64"/start_addr", - xen_domid, (uint64_t)physmap->phys_offset); - snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)physmap->start_add= r); - if (!xs_write(state->xenstore, 0, path, value, strlen(value))) { - return -1; - } - snprintf(path, sizeof(path), - "/local/domain/0/device-model/%d/physmap/%"PRIx64"/size", - xen_domid, (uint64_t)physmap->phys_offset); - snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)physmap->size); - if (!xs_write(state->xenstore, 0, path, value, strlen(value))) { - return -1; - } - if (physmap->name) { - snprintf(path, sizeof(path), - "/local/domain/0/device-model/%d/physmap/%"PRIx64"/name", - xen_domid, (uint64_t)physmap->phys_offset); - if (!xs_write(state->xenstore, 0, path, - physmap->name, strlen(physmap->name))) { - return -1; - } - } - return 0; -} -#else -static int xen_save_physmap(XenIOState *state, XenPhysmap *physmap) -{ - return 0; -} -#endif - -static int xen_add_to_physmap(XenIOState *state, - hwaddr start_addr, - ram_addr_t size, - MemoryRegion *mr, - hwaddr offset_within_region) -{ - unsigned target_page_bits =3D qemu_target_page_bits(); - int page_size =3D qemu_target_page_size(); - int page_mask =3D -page_size; - unsigned long nr_pages; - int rc =3D 0; - XenPhysmap *physmap =3D NULL; - hwaddr pfn, start_gpfn; - hwaddr phys_offset =3D memory_region_get_ram_addr(mr); - const char *mr_name; - - if (get_physmapping(start_addr, size, page_mask)) { - return 0; - } - if (size <=3D 0) { - return -1; - } - - /* Xen can only handle a single dirty log region for now and we want - * the linear framebuffer to be that region. - * Avoid tracking any regions that is not videoram and avoid tracking - * the legacy vga region. */ - if (mr =3D=3D framebuffer && start_addr > 0xbffff) { - goto go_physmap; - } - return -1; - -go_physmap: - DPRINTF("mapping vram to %"HWADDR_PRIx" - %"HWADDR_PRIx"\n", - start_addr, start_addr + size); - - mr_name =3D memory_region_name(mr); - - physmap =3D g_new(XenPhysmap, 1); - - physmap->start_addr =3D start_addr; - physmap->size =3D size; - physmap->name =3D mr_name; - physmap->phys_offset =3D phys_offset; - - QLIST_INSERT_HEAD(&xen_physmap, physmap, list); - - if (runstate_check(RUN_STATE_INMIGRATE)) { - /* Now when we have a physmap entry we can replace a dummy mapping= with - * a real one of guest foreign memory. */ - uint8_t *p =3D xen_replace_cache_entry(phys_offset, start_addr, si= ze); - assert(p && p =3D=3D memory_region_get_ram_ptr(mr)); - - return 0; - } - - pfn =3D phys_offset >> target_page_bits; - start_gpfn =3D start_addr >> target_page_bits; - nr_pages =3D size >> target_page_bits; - rc =3D xendevicemodel_relocate_memory(xen_dmod, xen_domid, nr_pages, p= fn, - start_gpfn); - if (rc) { - int saved_errno =3D errno; - - error_report("relocate_memory %lu pages from GFN %"HWADDR_PRIx - " to GFN %"HWADDR_PRIx" failed: %s", - nr_pages, pfn, start_gpfn, strerror(saved_errno)); - errno =3D saved_errno; - return -1; - } - - rc =3D xendevicemodel_pin_memory_cacheattr(xen_dmod, xen_domid, - start_addr >> target_page_bits, - (start_addr + size - 1) >> target_page_= bits, - XEN_DOMCTL_MEM_CACHEATTR_WB); - if (rc) { - error_report("pin_memory_cacheattr failed: %s", strerror(errno)); - } - return xen_save_physmap(state, physmap); -} - -static int xen_remove_from_physmap(XenIOState *state, - hwaddr start_addr, - ram_addr_t size) -{ - unsigned target_page_bits =3D qemu_target_page_bits(); - int page_size =3D qemu_target_page_size(); - int page_mask =3D -page_size; - int rc =3D 0; - XenPhysmap *physmap =3D NULL; - hwaddr phys_offset =3D 0; - - physmap =3D get_physmapping(start_addr, size, page_mask); - if (physmap =3D=3D NULL) { - return -1; - } - - phys_offset =3D physmap->phys_offset; - size =3D physmap->size; - - DPRINTF("unmapping vram to %"HWADDR_PRIx" - %"HWADDR_PRIx", at " - "%"HWADDR_PRIx"\n", start_addr, start_addr + size, phys_offset= ); - - size >>=3D target_page_bits; - start_addr >>=3D target_page_bits; - phys_offset >>=3D target_page_bits; - rc =3D xendevicemodel_relocate_memory(xen_dmod, xen_domid, size, start= _addr, - phys_offset); - if (rc) { - int saved_errno =3D errno; - - error_report("relocate_memory "RAM_ADDR_FMT" pages" - " from GFN %"HWADDR_PRIx - " to GFN %"HWADDR_PRIx" failed: %s", - size, start_addr, phys_offset, strerror(saved_errno)); - errno =3D saved_errno; - return -1; - } - - QLIST_REMOVE(physmap, list); - if (log_for_dirtybit =3D=3D physmap) { - log_for_dirtybit =3D NULL; - g_free(dirty_bitmap); - dirty_bitmap =3D NULL; - } - g_free(physmap); - - return 0; -} - -static void xen_sync_dirty_bitmap(XenIOState *state, - hwaddr start_addr, - ram_addr_t size) -{ - unsigned target_page_bits =3D qemu_target_page_bits(); - int page_size =3D qemu_target_page_size(); - int page_mask =3D -page_size; - hwaddr npages =3D size >> target_page_bits; - const int width =3D sizeof(unsigned long) * 8; - size_t bitmap_size =3D DIV_ROUND_UP(npages, width); - int rc, i, j; - const XenPhysmap *physmap =3D NULL; - - physmap =3D get_physmapping(start_addr, size, page_mask); - if (physmap =3D=3D NULL) { - /* not handled */ - return; - } - - if (log_for_dirtybit =3D=3D NULL) { - log_for_dirtybit =3D physmap; - dirty_bitmap =3D g_new(unsigned long, bitmap_size); - } else if (log_for_dirtybit !=3D physmap) { - /* Only one range for dirty bitmap can be tracked. */ - return; - } - - rc =3D xen_track_dirty_vram(xen_domid, start_addr >> target_page_bits, - npages, dirty_bitmap); - if (rc < 0) { -#ifndef ENODATA -#define ENODATA ENOENT -#endif - if (errno =3D=3D ENODATA) { - memory_region_set_dirty(framebuffer, 0, size); - DPRINTF("xen: track_dirty_vram failed (0x" HWADDR_FMT_plx - ", 0x" HWADDR_FMT_plx "): %s\n", - start_addr, start_addr + size, strerror(errno)); - } - return; - } - - for (i =3D 0; i < bitmap_size; i++) { - unsigned long map =3D dirty_bitmap[i]; - while (map !=3D 0) { - j =3D ctzl(map); - map &=3D ~(1ul << j); - memory_region_set_dirty(framebuffer, - (i * width + j) * page_size, - page_size); - }; - } -} - -static void xen_log_start(MemoryListener *listener, - MemoryRegionSection *section, - int old, int new) -{ - XenIOState *state =3D container_of(listener, XenIOState, memory_listen= er); - - if (new & ~old & (1 << DIRTY_MEMORY_VGA)) { - xen_sync_dirty_bitmap(state, section->offset_within_address_space, - int128_get64(section->size)); - } -} - -static void xen_log_stop(MemoryListener *listener, MemoryRegionSection *se= ction, - int old, int new) -{ - if (old & ~new & (1 << DIRTY_MEMORY_VGA)) { - log_for_dirtybit =3D NULL; - g_free(dirty_bitmap); - dirty_bitmap =3D NULL; - /* Disable dirty bit tracking */ - xen_track_dirty_vram(xen_domid, 0, 0, NULL); - } -} - -static void xen_log_sync(MemoryListener *listener, MemoryRegionSection *se= ction) -{ - XenIOState *state =3D container_of(listener, XenIOState, memory_listen= er); - - xen_sync_dirty_bitmap(state, section->offset_within_address_space, - int128_get64(section->size)); -} - -static void xen_log_global_start(MemoryListener *listener) -{ - if (xen_enabled()) { - xen_in_migration =3D true; - } -} - -static void xen_log_global_stop(MemoryListener *listener) -{ - xen_in_migration =3D false; -} - -const MemoryListener xen_memory_listener =3D { - .name =3D "xen-memory", - .region_add =3D xen_region_add, - .region_del =3D xen_region_del, - .log_start =3D xen_log_start, - .log_stop =3D xen_log_stop, - .log_sync =3D xen_log_sync, - .log_global_start =3D xen_log_global_start, - .log_global_stop =3D xen_log_global_stop, - .priority =3D MEMORY_LISTENER_PRIORITY_ACCEL, -}; - -#ifdef XEN_COMPAT_PHYSMAP -void xen_read_physmap(XenIOState *state) -{ - XenPhysmap *physmap =3D NULL; - unsigned int len, num, i; - char path[80], *value =3D NULL; - char **entries =3D NULL; - - QLIST_INIT(&xen_physmap); - - snprintf(path, sizeof(path), - "/local/domain/0/device-model/%d/physmap", xen_domid); - entries =3D xs_directory(state->xenstore, 0, path, &num); - if (entries =3D=3D NULL) - return; - - for (i =3D 0; i < num; i++) { - physmap =3D g_new(XenPhysmap, 1); - physmap->phys_offset =3D strtoull(entries[i], NULL, 16); - snprintf(path, sizeof(path), - "/local/domain/0/device-model/%d/physmap/%s/start_addr", - xen_domid, entries[i]); - value =3D xs_read(state->xenstore, 0, path, &len); - if (value =3D=3D NULL) { - g_free(physmap); - continue; - } - physmap->start_addr =3D strtoull(value, NULL, 16); - free(value); - - snprintf(path, sizeof(path), - "/local/domain/0/device-model/%d/physmap/%s/size", - xen_domid, entries[i]); - value =3D xs_read(state->xenstore, 0, path, &len); - if (value =3D=3D NULL) { - g_free(physmap); - continue; - } - physmap->size =3D strtoull(value, NULL, 16); - free(value); - - snprintf(path, sizeof(path), - "/local/domain/0/device-model/%d/physmap/%s/name", - xen_domid, entries[i]); - physmap->name =3D xs_read(state->xenstore, 0, path, &len); - - QLIST_INSERT_HEAD(&xen_physmap, physmap, list); - } - free(entries); -} -#else -void xen_read_physmap(XenIOState *state) -{ - QLIST_INIT(&xen_physmap); -} -#endif - -void xen_register_framebuffer(MemoryRegion *mr) -{ - framebuffer =3D mr; -} - -void xen_hvm_modified_memory(ram_addr_t start, ram_addr_t length) -{ - unsigned target_page_bits =3D qemu_target_page_bits(); - int page_size =3D qemu_target_page_size(); - int page_mask =3D -page_size; - - if (unlikely(xen_in_migration)) { - int rc; - ram_addr_t start_pfn, nb_pages; - - start =3D xen_phys_offset_to_gaddr(start, length, page_mask); - - if (length =3D=3D 0) { - length =3D page_size; - } - start_pfn =3D start >> target_page_bits; - nb_pages =3D ((start + length + page_size - 1) >> target_page_bits) - - start_pfn; - rc =3D xen_modified_memory(xen_domid, start_pfn, nb_pages); - if (rc) { - fprintf(stderr, - "%s failed for "RAM_ADDR_FMT" ("RAM_ADDR_FMT"): %i, %s= \n", - __func__, start, nb_pages, errno, strerror(errno)); - } - } -} - -void qmp_xen_set_global_dirty_log(bool enable, Error **errp) -{ - if (enable) { - memory_global_dirty_log_start(GLOBAL_DIRTY_MIGRATION); - } else { - memory_global_dirty_log_stop(GLOBAL_DIRTY_MIGRATION); - } -} - -void xen_arch_set_memory(XenIOState *state, MemoryRegionSection *section, - bool add) -{ - unsigned target_page_bits =3D qemu_target_page_bits(); - int page_size =3D qemu_target_page_size(); - int page_mask =3D -page_size; - hwaddr start_addr =3D section->offset_within_address_space; - ram_addr_t size =3D int128_get64(section->size); - bool log_dirty =3D memory_region_is_logging(section->mr, DIRTY_MEMORY_= VGA); - hvmmem_type_t mem_type; - - if (!memory_region_is_ram(section->mr)) { - return; - } - - if (log_dirty !=3D add) { - return; - } - - trace_xen_client_set_memory(start_addr, size, log_dirty); - - start_addr &=3D page_mask; - size =3D ROUND_UP(size, page_size); - - if (add) { - if (!memory_region_is_rom(section->mr)) { - xen_add_to_physmap(state, start_addr, size, - section->mr, section->offset_within_region); - } else { - mem_type =3D HVMMEM_ram_ro; - if (xen_set_mem_type(xen_domid, mem_type, - start_addr >> target_page_bits, - size >> target_page_bits)) { - DPRINTF("xen_set_mem_type error, addr: "HWADDR_FMT_plx"\n", - start_addr); - } - } - } else { - if (xen_remove_from_physmap(state, start_addr, size) < 0) { - DPRINTF("physmapping does not exist at "HWADDR_FMT_plx"\n", st= art_addr); - } - } -} diff --git a/hw/xen/xen-hvm-common.c b/hw/xen/xen-hvm-common.c index 73fa2c414d..50ce45effc 100644 --- a/hw/xen/xen-hvm-common.c +++ b/hw/xen/xen-hvm-common.c @@ -1,7 +1,9 @@ #include "qemu/osdep.h" #include "qemu/units.h" #include "qemu/bitops.h" +#include "qemu/range.h" #include "qapi/error.h" +#include "qapi/qapi-commands-migration.h" #include "exec/target_page.h" #include "trace.h" =20 @@ -11,6 +13,462 @@ #include "hw/boards.h" =20 MemoryRegion xen_memory; +static MemoryRegion *framebuffer; +static bool xen_in_migration; + +static QLIST_HEAD(, XenPhysmap) xen_physmap; +static const XenPhysmap *log_for_dirtybit; +/* Buffer used by xen_sync_dirty_bitmap */ +static unsigned long *dirty_bitmap; + +static XenPhysmap *get_physmapping(hwaddr start_addr, ram_addr_t size, + int page_mask) +{ + XenPhysmap *physmap =3D NULL; + + start_addr &=3D -page_mask; + + QLIST_FOREACH(physmap, &xen_physmap, list) { + if (range_covers_byte(physmap->start_addr, physmap->size, start_ad= dr)) { + return physmap; + } + } + return NULL; +} + +static hwaddr xen_phys_offset_to_gaddr(hwaddr phys_offset, ram_addr_t size, + int page_mask) +{ + hwaddr addr =3D phys_offset & -page_mask; + XenPhysmap *physmap =3D NULL; + + QLIST_FOREACH(physmap, &xen_physmap, list) { + if (range_covers_byte(physmap->phys_offset, physmap->size, addr)) { + return physmap->start_addr + (phys_offset - physmap->phys_offs= et); + } + } + + return phys_offset; +} + +#ifdef XEN_COMPAT_PHYSMAP +static int xen_save_physmap(XenIOState *state, XenPhysmap *physmap) +{ + char path[80], value[17]; + + snprintf(path, sizeof(path), + "/local/domain/0/device-model/%d/physmap/%"PRIx64"/start_addr", + xen_domid, (uint64_t)physmap->phys_offset); + snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)physmap->start_add= r); + if (!xs_write(state->xenstore, 0, path, value, strlen(value))) { + return -1; + } + snprintf(path, sizeof(path), + "/local/domain/0/device-model/%d/physmap/%"PRIx64"/size", + xen_domid, (uint64_t)physmap->phys_offset); + snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)physmap->size); + if (!xs_write(state->xenstore, 0, path, value, strlen(value))) { + return -1; + } + if (physmap->name) { + snprintf(path, sizeof(path), + "/local/domain/0/device-model/%d/physmap/%"PRIx64"/name", + xen_domid, (uint64_t)physmap->phys_offset); + if (!xs_write(state->xenstore, 0, path, + physmap->name, strlen(physmap->name))) { + return -1; + } + } + return 0; +} +#else +static int xen_save_physmap(XenIOState *state, XenPhysmap *physmap) +{ + return 0; +} +#endif + +static int xen_add_to_physmap(XenIOState *state, + hwaddr start_addr, + ram_addr_t size, + MemoryRegion *mr, + hwaddr offset_within_region) +{ + unsigned target_page_bits =3D qemu_target_page_bits(); + int page_size =3D qemu_target_page_size(); + int page_mask =3D -page_size; + unsigned long nr_pages; + int rc =3D 0; + XenPhysmap *physmap =3D NULL; + hwaddr pfn, start_gpfn; + hwaddr phys_offset =3D memory_region_get_ram_addr(mr); + const char *mr_name; + + if (get_physmapping(start_addr, size, page_mask)) { + return 0; + } + if (size <=3D 0) { + return -1; + } + + /* Xen can only handle a single dirty log region for now and we want + * the linear framebuffer to be that region. + * Avoid tracking any regions that is not videoram and avoid tracking + * the legacy vga region. */ + if (mr =3D=3D framebuffer && start_addr > 0xbffff) { + goto go_physmap; + } + return -1; + +go_physmap: + DPRINTF("mapping vram to %"HWADDR_PRIx" - %"HWADDR_PRIx"\n", + start_addr, start_addr + size); + + mr_name =3D memory_region_name(mr); + + physmap =3D g_new(XenPhysmap, 1); + + physmap->start_addr =3D start_addr; + physmap->size =3D size; + physmap->name =3D mr_name; + physmap->phys_offset =3D phys_offset; + + QLIST_INSERT_HEAD(&xen_physmap, physmap, list); + + if (runstate_check(RUN_STATE_INMIGRATE)) { + /* Now when we have a physmap entry we can replace a dummy mapping= with + * a real one of guest foreign memory. */ + uint8_t *p =3D xen_replace_cache_entry(phys_offset, start_addr, si= ze); + assert(p && p =3D=3D memory_region_get_ram_ptr(mr)); + + return 0; + } + + pfn =3D phys_offset >> target_page_bits; + start_gpfn =3D start_addr >> target_page_bits; + nr_pages =3D size >> target_page_bits; + rc =3D xendevicemodel_relocate_memory(xen_dmod, xen_domid, nr_pages, p= fn, + start_gpfn); + if (rc) { + int saved_errno =3D errno; + + error_report("relocate_memory %lu pages from GFN %"HWADDR_PRIx + " to GFN %"HWADDR_PRIx" failed: %s", + nr_pages, pfn, start_gpfn, strerror(saved_errno)); + errno =3D saved_errno; + return -1; + } + + rc =3D xendevicemodel_pin_memory_cacheattr(xen_dmod, xen_domid, + start_addr >> target_page_bits, + (start_addr + size - 1) >> target_page_= bits, + XEN_DOMCTL_MEM_CACHEATTR_WB); + if (rc) { + error_report("pin_memory_cacheattr failed: %s", strerror(errno)); + } + return xen_save_physmap(state, physmap); +} + +static int xen_remove_from_physmap(XenIOState *state, + hwaddr start_addr, + ram_addr_t size) +{ + unsigned target_page_bits =3D qemu_target_page_bits(); + int page_size =3D qemu_target_page_size(); + int page_mask =3D -page_size; + int rc =3D 0; + XenPhysmap *physmap =3D NULL; + hwaddr phys_offset =3D 0; + + physmap =3D get_physmapping(start_addr, size, page_mask); + if (physmap =3D=3D NULL) { + return -1; + } + + phys_offset =3D physmap->phys_offset; + size =3D physmap->size; + + DPRINTF("unmapping vram to %"HWADDR_PRIx" - %"HWADDR_PRIx", at " + "%"HWADDR_PRIx"\n", start_addr, start_addr + size, phys_offset= ); + + size >>=3D target_page_bits; + start_addr >>=3D target_page_bits; + phys_offset >>=3D target_page_bits; + rc =3D xendevicemodel_relocate_memory(xen_dmod, xen_domid, size, start= _addr, + phys_offset); + if (rc) { + int saved_errno =3D errno; + + error_report("relocate_memory "RAM_ADDR_FMT" pages" + " from GFN %"HWADDR_PRIx + " to GFN %"HWADDR_PRIx" failed: %s", + size, start_addr, phys_offset, strerror(saved_errno)); + errno =3D saved_errno; + return -1; + } + + QLIST_REMOVE(physmap, list); + if (log_for_dirtybit =3D=3D physmap) { + log_for_dirtybit =3D NULL; + g_free(dirty_bitmap); + dirty_bitmap =3D NULL; + } + g_free(physmap); + + return 0; +} + +static void xen_sync_dirty_bitmap(XenIOState *state, + hwaddr start_addr, + ram_addr_t size) +{ + unsigned target_page_bits =3D qemu_target_page_bits(); + int page_size =3D qemu_target_page_size(); + int page_mask =3D -page_size; + hwaddr npages =3D size >> target_page_bits; + const int width =3D sizeof(unsigned long) * 8; + size_t bitmap_size =3D DIV_ROUND_UP(npages, width); + int rc, i, j; + const XenPhysmap *physmap =3D NULL; + + physmap =3D get_physmapping(start_addr, size, page_mask); + if (physmap =3D=3D NULL) { + /* not handled */ + return; + } + + if (log_for_dirtybit =3D=3D NULL) { + log_for_dirtybit =3D physmap; + dirty_bitmap =3D g_new(unsigned long, bitmap_size); + } else if (log_for_dirtybit !=3D physmap) { + /* Only one range for dirty bitmap can be tracked. */ + return; + } + + rc =3D xen_track_dirty_vram(xen_domid, start_addr >> target_page_bits, + npages, dirty_bitmap); + if (rc < 0) { +#ifndef ENODATA +#define ENODATA ENOENT +#endif + if (errno =3D=3D ENODATA) { + memory_region_set_dirty(framebuffer, 0, size); + DPRINTF("xen: track_dirty_vram failed (0x" HWADDR_FMT_plx + ", 0x" HWADDR_FMT_plx "): %s\n", + start_addr, start_addr + size, strerror(errno)); + } + return; + } + + for (i =3D 0; i < bitmap_size; i++) { + unsigned long map =3D dirty_bitmap[i]; + while (map !=3D 0) { + j =3D ctzl(map); + map &=3D ~(1ul << j); + memory_region_set_dirty(framebuffer, + (i * width + j) * page_size, + page_size); + }; + } +} + +static void xen_log_start(MemoryListener *listener, + MemoryRegionSection *section, + int old, int new) +{ + XenIOState *state =3D container_of(listener, XenIOState, memory_listen= er); + + if (new & ~old & (1 << DIRTY_MEMORY_VGA)) { + xen_sync_dirty_bitmap(state, section->offset_within_address_space, + int128_get64(section->size)); + } +} + +static void xen_log_stop(MemoryListener *listener, MemoryRegionSection *se= ction, + int old, int new) +{ + if (old & ~new & (1 << DIRTY_MEMORY_VGA)) { + log_for_dirtybit =3D NULL; + g_free(dirty_bitmap); + dirty_bitmap =3D NULL; + /* Disable dirty bit tracking */ + xen_track_dirty_vram(xen_domid, 0, 0, NULL); + } +} + +static void xen_log_sync(MemoryListener *listener, MemoryRegionSection *se= ction) +{ + XenIOState *state =3D container_of(listener, XenIOState, memory_listen= er); + + xen_sync_dirty_bitmap(state, section->offset_within_address_space, + int128_get64(section->size)); +} + +static void xen_log_global_start(MemoryListener *listener) +{ + if (xen_enabled()) { + xen_in_migration =3D true; + } +} + +static void xen_log_global_stop(MemoryListener *listener) +{ + xen_in_migration =3D false; +} + +const MemoryListener xen_memory_listener =3D { + .name =3D "xen-memory", + .region_add =3D xen_region_add, + .region_del =3D xen_region_del, + .log_start =3D xen_log_start, + .log_stop =3D xen_log_stop, + .log_sync =3D xen_log_sync, + .log_global_start =3D xen_log_global_start, + .log_global_stop =3D xen_log_global_stop, + .priority =3D MEMORY_LISTENER_PRIORITY_ACCEL, +}; + +#ifdef XEN_COMPAT_PHYSMAP +void xen_read_physmap(XenIOState *state) +{ + XenPhysmap *physmap =3D NULL; + unsigned int len, num, i; + char path[80], *value =3D NULL; + char **entries =3D NULL; + + QLIST_INIT(&xen_physmap); + + snprintf(path, sizeof(path), + "/local/domain/0/device-model/%d/physmap", xen_domid); + entries =3D xs_directory(state->xenstore, 0, path, &num); + if (entries =3D=3D NULL) + return; + + for (i =3D 0; i < num; i++) { + physmap =3D g_new(XenPhysmap, 1); + physmap->phys_offset =3D strtoull(entries[i], NULL, 16); + snprintf(path, sizeof(path), + "/local/domain/0/device-model/%d/physmap/%s/start_addr", + xen_domid, entries[i]); + value =3D xs_read(state->xenstore, 0, path, &len); + if (value =3D=3D NULL) { + g_free(physmap); + continue; + } + physmap->start_addr =3D strtoull(value, NULL, 16); + free(value); + + snprintf(path, sizeof(path), + "/local/domain/0/device-model/%d/physmap/%s/size", + xen_domid, entries[i]); + value =3D xs_read(state->xenstore, 0, path, &len); + if (value =3D=3D NULL) { + g_free(physmap); + continue; + } + physmap->size =3D strtoull(value, NULL, 16); + free(value); + + snprintf(path, sizeof(path), + "/local/domain/0/device-model/%d/physmap/%s/name", + xen_domid, entries[i]); + physmap->name =3D xs_read(state->xenstore, 0, path, &len); + + QLIST_INSERT_HEAD(&xen_physmap, physmap, list); + } + free(entries); +} +#else +void xen_read_physmap(XenIOState *state) +{ + QLIST_INIT(&xen_physmap); +} +#endif + +void xen_register_framebuffer(MemoryRegion *mr) +{ + framebuffer =3D mr; +} + +void xen_hvm_modified_memory(ram_addr_t start, ram_addr_t length) +{ + unsigned target_page_bits =3D qemu_target_page_bits(); + int page_size =3D qemu_target_page_size(); + int page_mask =3D -page_size; + + if (unlikely(xen_in_migration)) { + int rc; + ram_addr_t start_pfn, nb_pages; + + start =3D xen_phys_offset_to_gaddr(start, length, page_mask); + + if (length =3D=3D 0) { + length =3D page_size; + } + start_pfn =3D start >> target_page_bits; + nb_pages =3D ((start + length + page_size - 1) >> target_page_bits) + - start_pfn; + rc =3D xen_modified_memory(xen_domid, start_pfn, nb_pages); + if (rc) { + fprintf(stderr, + "%s failed for "RAM_ADDR_FMT" ("RAM_ADDR_FMT"): %i, %s= \n", + __func__, start, nb_pages, errno, strerror(errno)); + } + } +} + +void qmp_xen_set_global_dirty_log(bool enable, Error **errp) +{ + if (enable) { + memory_global_dirty_log_start(GLOBAL_DIRTY_MIGRATION); + } else { + memory_global_dirty_log_stop(GLOBAL_DIRTY_MIGRATION); + } +} + +void xen_arch_set_memory(XenIOState *state, MemoryRegionSection *section, + bool add) +{ + unsigned target_page_bits =3D qemu_target_page_bits(); + int page_size =3D qemu_target_page_size(); + int page_mask =3D -page_size; + hwaddr start_addr =3D section->offset_within_address_space; + ram_addr_t size =3D int128_get64(section->size); + bool log_dirty =3D memory_region_is_logging(section->mr, DIRTY_MEMORY_= VGA); + hvmmem_type_t mem_type; + + if (!memory_region_is_ram(section->mr)) { + return; + } + + if (log_dirty !=3D add) { + return; + } + + trace_xen_client_set_memory(start_addr, size, log_dirty); + + start_addr &=3D page_mask; + size =3D ROUND_UP(size, page_size); + + if (add) { + if (!memory_region_is_rom(section->mr)) { + xen_add_to_physmap(state, start_addr, size, + section->mr, section->offset_within_region); + } else { + mem_type =3D HVMMEM_ram_ro; + if (xen_set_mem_type(xen_domid, mem_type, + start_addr >> target_page_bits, + size >> target_page_bits)) { + DPRINTF("xen_set_mem_type error, addr: "HWADDR_FMT_plx"\n", + start_addr); + } + } + } else { + if (xen_remove_from_physmap(state, start_addr, size) < 0) { + DPRINTF("physmapping does not exist at "HWADDR_FMT_plx"\n", st= art_addr); + } + } +} =20 void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr, Error **errp) diff --git a/stubs/xen-hw-stub.c b/stubs/xen-hw-stub.c index 53c6a6f2a0..da8912f037 100644 --- a/stubs/xen-hw-stub.c +++ b/stubs/xen-hw-stub.c @@ -13,7 +13,3 @@ int xen_is_pirq_msi(uint32_t msi_data) { return 0; } - -void xen_register_framebuffer(MemoryRegion *mr) -{ -} diff --git a/hw/i386/xen/meson.build b/hw/i386/xen/meson.build index d38759cfe4..3f0df8bc07 100644 --- a/hw/i386/xen/meson.build +++ b/hw/i386/xen/meson.build @@ -1,7 +1,6 @@ i386_ss.add(when: 'CONFIG_XEN', if_true: files( 'xen_apic.c', 'xen_pvdevice.c', - 'xen-hvm-common.c', )) i386_ss.add(when: ['CONFIG_XEN', xen], if_true: files( 'xen-hvm.c', --=20 2.41.0