From nobody Wed Aug 26 01:48:52 2026 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=quarantine dis=none) header.from=suse.com ARC-Seal: i=1; a=rsa-sha256; t=1785248447; cv=none; d=zohomail.com; s=zohoarc; b=AD84JhczNz1hX2IcrqDzqoe6ZHuYFdFO4vOV3jSFGZhGhOZXutnJZLTZqea0A9FMEHXsXFCj8P5yfsh76ems/dP0r/zA5/maFJ42RKIa59XFpvL1uwMsDUtpj6EdbxPQWHbWPU5KdjIrZFgkgt66RObr1Qu4LXy5ayNe7QVauOQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785248447; 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=3K1J9tuZW+tws4Xjl6Dh8DcJ/c/koNpFTzCSwtVmdwo=; b=DGpOCS7KITLofhlTGChsfNBWyGkt1t/XCeheSqL9Be5sKBQ+R2rELIDv3K1BeEH3jfoiXn2uuA/GoQ5G5ei8HVRAFw8DuVGGyQrWh39GdQdS/XJAWHnV68F2ROX5a+qalMMcwNKqqduF1gbQQh1TQdDOOt8rGsEtpbj5zE3s57c= 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=quarantine dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1785248447122148.62116260677772; Tue, 28 Jul 2026 07:20:47 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1374353.1621504 (Exim 4.92) (envelope-from ) id 1woifZ-0000qL-A0; Tue, 28 Jul 2026 14:20:33 +0000 Received: by outflank-mailman (output) from mailman id 1374353.1621504; Tue, 28 Jul 2026 14:20:33 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1woifZ-0000qE-7D; Tue, 28 Jul 2026 14:20:33 +0000 Received: by outflank-mailman (input) for mailman id 1374353; Tue, 28 Jul 2026 14:20:32 +0000 Received: from mx.expurgate.net ([194.145.224.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1woifY-0000oK-9I for xen-devel@lists.xenproject.org; Tue, 28 Jul 2026 14:20:32 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1woifX-00HNLM-LE for xen-devel@lists.xenproject.org; Tue, 28 Jul 2026 16:20:31 +0200 Received: from [10.42.69.11] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a68baa1-2eae-0a2a0a5409dd-0a2a450ba534-38 for ; Tue, 28 Jul 2026 16:20:31 +0200 Received: from [209.85.221.53] (helo=mail-wr1-f53.google.com) by tlsNG-42698a.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a68baaf-b7e8-0a2a450b0019-d155dd35b4af-3 for ; Tue, 28 Jul 2026 16:20:31 +0200 Received: by mail-wr1-f53.google.com with SMTP id ffacd0b85a97d-47f81a3ccf9so2477125f8f.0 for ; Tue, 28 Jul 2026 07:20:31 -0700 (PDT) Received: from [10.156.60.236] (ip-037-024-206-209.um08.pools.vodafone-ip.de. [37.24.206.209]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-47f85c63678sm55327159f8f.29.2026.07.28.07.20.29 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 28 Jul 2026 07:20:30 -0700 (PDT) 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" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=google header.d=suse.com header.i="@suse.com" header.h="Content-Transfer-Encoding:Content-Type:In-Reply-To:Autocrypt:Content-Language:References:Cc:To:From:Subject:User-Agent:MIME-Version:Date:Message-ID" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=google; t=1785248431; x=1785853231; darn=lists.xenproject.org; h=content-transfer-encoding:content-type:in-reply-to:autocrypt :content-language:references:cc:to:from:subject:user-agent :mime-version:date:message-id:from:to:cc:subject:date:message-id :reply-to:content-type; bh=3K1J9tuZW+tws4Xjl6Dh8DcJ/c/koNpFTzCSwtVmdwo=; b=eqUjGelfrWah4/b2cFwGSGNKZoX6DJjPp2506KFasGwJObiv3dr59ULpK42qCRY6td LjgdXFLqLzj84yqOWIXpQTsgSUI1noYYJgEAOhZ/bUSueB1FSlWjmHidTU4Vwym8397+ Zj6ZHyAhzHKewnAW90oBU+oXyzo/cqMvpdywhNheZN488nyprOL4NVy8Q/nol2Fs6mL1 Is2ke36pZjdj/ZYy2cOoyt2h/03M8XtoExynnTfVQHKqYFXDK2X63VF0MUdkO/HZ7FGJ nZE6dulCDpvmMK40eNYW6bnIhb0xh1wChL1E01Ry3ruacI+mJpYorq+GmNefRJ9QVRMP c/vA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785248431; x=1785853231; h=content-transfer-encoding:content-type:in-reply-to:autocrypt :content-language:references:cc:to:from:subject:user-agent :mime-version:date:message-id:x-gm-gg:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to:content-type; bh=3K1J9tuZW+tws4Xjl6Dh8DcJ/c/koNpFTzCSwtVmdwo=; b=eMYKrMaAj8PmN8AOaY1oej/mtjjg2d2HUmFx7zx347vcHsR6kdDnFnvTQWZgGaoorG q7H29qqGKzGKCsN1oISApXkJVWXHtm41bhFlq4H1AgjDMdhgKLGqmVaOejXD8iDEESrg onfDb9vqHlxba7/vyhYhnGIgl7bUlhLHba5ESJo92jPEK/QaUAHf1ErwkZu9kry1R11R ekW4nv8r6a1L+xmCeB7vmonHa4jMulc4hlHzsPMWLQIn6S9gwcp/e3fZ5n6dwhMlN4Hi jsbeMPRoIVBeJnXAn3mOe01XQ/vGmWZJUXJSXJuzWaB2YT5BXEgfVZfEfh1kH3NeKLAJ SJ/A== X-Gm-Message-State: AOJu0Yw8fS6WFY4d4blt0jhIXwfQmbnyHoumxqzBfBRmQiqUG9RoF21E chAMIBC1vjWnzAVM1uX3DkFWXrlQC4DO/exkDTa/jlCLNeTYB9Y+GnnvQgzGCAsktRgUv8w3doK Nhsh9Zg== X-Gm-Gg: AR+sD111UsVt74Z6Hwh5JL2yAy7hZHiLAeM8jWt8U822uWIrU/D2dmH5uL4og1obUYI sYHZtKOEYN9emEhC2JvU2pnYm0xJvCky9XOYblj3m6tZWDMsb/ToZUv2kJrp31vC5zF/aT+Yja/ S/ZA2i2mB7iibOldlQp1SkSN5IB7Ee5QDoAbzWnOaqtB/fdcvdTQBnDhhEzcdQ3W1eSiI+7MoUZ Z+MShNQto7urgyJRxdbkNETtKHwviFIabuV/oFkKNIoAaqtqdGSaxevVXIXZG4HjG5QggDp8aGy OREmaeB3LBsbwezxLAzhkvBCLBZMSS68ll405ariteSo3HdAyJQubxv2ssjy+1wMJgiriuHRGb6 4lCiFZChPpIYWm7WlNYaNmLhtaCC/QU8PorQ+aAxrVWWDdrogFaFWMS5dy7flBdN7ZGREGEbXfz D72MIoITQPYCxHjUN8FAWNjkw9zQfqXswf6oYDKALEe22MJStY32ZCpVZSBlRRR/JD2vu6suh0m Qqd X-Received: by 2002:a05:6000:3110:b0:46e:6201:3ebc with SMTP id ffacd0b85a97d-47fb1f18031mr3328707f8f.41.1785248430582; Tue, 28 Jul 2026 07:20:30 -0700 (PDT) Message-ID: <5fe59b1f-70d9-46e7-b7f8-c5e8321d451a@suse.com> Date: Tue, 28 Jul 2026 16:20:29 +0200 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: [PATCH v15 01/10] x86/shadow: add preemption support to shadow_blow_tables() From: Jan Beulich To: "xen-devel@lists.xenproject.org" Cc: Andrew Cooper , Tim Deegan References: <68c16600-a4bf-4060-a1fc-56c4ae655b03@suse.com> Content-Language: en-US Autocrypt: addr=jbeulich@suse.com; keydata= xsDiBFk3nEQRBADAEaSw6zC/EJkiwGPXbWtPxl2xCdSoeepS07jW8UgcHNurfHvUzogEq5xk hu507c3BarVjyWCJOylMNR98Yd8VqD9UfmX0Hb8/BrA+Hl6/DB/eqGptrf4BSRwcZQM32aZK 7Pj2XbGWIUrZrd70x1eAP9QE3P79Y2oLrsCgbZJfEwCgvz9JjGmQqQkRiTVzlZVCJYcyGGsD /0tbFCzD2h20ahe8rC1gbb3K3qk+LpBtvjBu1RY9drYk0NymiGbJWZgab6t1jM7sk2vuf0Py O9Hf9XBmK0uE9IgMaiCpc32XV9oASz6UJebwkX+zF2jG5I1BfnO9g7KlotcA/v5ClMjgo6Gl MDY4HxoSRu3i1cqqSDtVlt+AOVBJBACrZcnHAUSuCXBPy0jOlBhxPqRWv6ND4c9PH1xjQ3NP nxJuMBS8rnNg22uyfAgmBKNLpLgAGVRMZGaGoJObGf72s6TeIqKJo/LtggAS9qAUiuKVnygo 3wjfkS9A3DRO+SpU7JqWdsveeIQyeyEJ/8PTowmSQLakF+3fote9ybzd880fSmFuIEJldWxp Y2ggPGpiZXVsaWNoQHN1c2UuY29tPsJgBBMRAgAgBQJZN5xEAhsDBgsJCAcDAgQVAggDBBYC AwECHgECF4AACgkQoDSui/t3IH4J+wCfQ5jHdEjCRHj23O/5ttg9r9OIruwAn3103WUITZee e7Sbg12UgcQ5lv7SzsFNBFk3nEQQCACCuTjCjFOUdi5Nm244F+78kLghRcin/awv+IrTcIWF hUpSs1Y91iQQ7KItirz5uwCPlwejSJDQJLIS+QtJHaXDXeV6NI0Uef1hP20+y8qydDiVkv6l IreXjTb7DvksRgJNvCkWtYnlS3mYvQ9NzS9PhyALWbXnH6sIJd2O9lKS1Mrfq+y0IXCP10eS FFGg+Av3IQeFatkJAyju0PPthyTqxSI4lZYuJVPknzgaeuJv/2NccrPvmeDg6Coe7ZIeQ8Yj t0ARxu2xytAkkLCel1Lz1WLmwLstV30g80nkgZf/wr+/BXJW/oIvRlonUkxv+IbBM3dX2OV8 AmRv1ySWPTP7AAMFB/9PQK/VtlNUJvg8GXj9ootzrteGfVZVVT4XBJkfwBcpC/XcPzldjv+3 HYudvpdNK3lLujXeA5fLOH+Z/G9WBc5pFVSMocI71I8bT8lIAzreg0WvkWg5V2WZsUMlnDL9 mpwIGFhlbM3gfDMs7MPMu8YQRFVdUvtSpaAs8OFfGQ0ia3LGZcjA6Ik2+xcqscEJzNH+qh8V m5jjp28yZgaqTaRbg3M/+MTbMpicpZuqF4rnB0AQD12/3BNWDR6bmh+EkYSMcEIpQmBM51qM EKYTQGybRCjpnKHGOxG0rfFY1085mBDZCH5Kx0cl0HVJuQKC+dV2ZY5AqjcKwAxpE75MLFkr wkkEGBECAAkFAlk3nEQCGwwACgkQoDSui/t3IH7nnwCfcJWUDUFKdCsBH/E5d+0ZnMQi+G0A nAuWpQkjM1ASeQwSHEeAWPgskBQL In-Reply-To: <68c16600-a4bf-4060-a1fc-56c4ae655b03@suse.com> Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-42698a/1785248431-182F49EA-C54BFBF1/0/0 X-purgate-type: clean X-purgate-size: 7208 X-ZohoMail-DKIM: pass (identity @suse.com) X-ZM-MESSAGEID: 1785248448384158500 From: Roger Pau Monn=C3=A9 The use of shadow_blow_tables() in the domain teardown path (added for XSA-410) actually requires preemption support itself for security reasons, specially as the pages freed by shadow_blow_tables() are not returned to the shadow page pool, but instead freed to the hypervisor. Note that we require flushing the TLB when a need for preemption arises on the 2nd pass, or else we risk returning to guest context with stale TLB entries. (There's no similar need on the 1st pass, as per _shadow_prealloc().) While preemption will be enabled only when tearing down domains (and hence flushing has become meaningless by that point), keep the function structured to no bypass the flush, just in case. Signed-off-by: Roger Pau Monn=C3=A9 Signed-off-by: Jan Beulich Acked-by: Tim Deegan --- Changes since v12: - Re-base. Changes since v11: - Re-base in particular past the XSA-410 series. Changes since v9: - Extend a comment. Commit message adjustments. Changes since v8: - Use difference, not sum, of total and free pages to determine whether progress was made. - Check for preemption on every iteration of the 2nd pass, as long as some progress was made. - Don't "goto out" on the 1st pass, to skip the TLB flush. Changes since v6: - Rearrange order of preemption condition checks. - Only avoid shadow_blow_tables() when the domain is dead (ie: all vCPUs are stopped). Changes since v5: - Add comment, remove no functional change. - Do not check for preemption on every loop. Changes since v4: - New in this version. --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -454,12 +454,23 @@ bool shadow_prealloc(struct domain *d, u =20 /* Deliberately free all the memory we can: this will tear down all of * this domain's shadows */ -void shadow_blow_tables(struct domain *d) +void shadow_blow_tables(struct domain *d, bool *preempted) { struct page_info *sp, *t; struct vcpu *v; mfn_t smfn; int i; + unsigned int done =3D 0; + + /* + * When the domain is dying a call to shadow_blow_tables() will be + * performed from the teardown path with preemption support, ignore any + * other calls as we want to do the final teardown with preemption sup= port. + * Teardown of shadow related data can only be avoided when all domain + * vCPUs are stopped. + */ + if ( unlikely(d->is_dying) && !preempted ) + return; =20 /* Nothing to do when there are no vcpus yet. */ if ( !d->vcpu[0] ) @@ -470,17 +481,46 @@ void shadow_blow_tables(struct domain *d { smfn =3D page_to_mfn(sp); sh_unpin(d, smfn); + if ( preempted && !(++done & 0xff) && general_preempt_check() ) + { + *preempted =3D true; + return; + } } =20 /* Second pass: unhook entries of in-use shadows */ for_each_vcpu(d, v) for ( i =3D 0; i < ARRAY_SIZE(v->arch.paging.shadow.shadow_table);= i++ ) if ( !pagetable_is_null(v->arch.paging.shadow.shadow_table[i])= ) + { + unsigned int num =3D d->arch.paging.total_pages - + d->arch.paging.free_pages; + shadow_unhook_mappings( d, pagetable_get_mfn(v->arch.paging.shadow.shadow_table[i= ]), 0); =20 + /* + * Make sure we are making progress before yielding: if do= main + * is dying progress will be seen by total_pages decreasin= g, if + * not dying free_pages will increase. In any case the gap + * between both will shrink. + * + * Note that with the paging lock held the values used in = the + * calculation are safe from being altered by other hyperc= alls. + */ + if ( preempted && + (num !=3D d->arch.paging.total_pages - + d->arch.paging.free_pages) && + general_preempt_check() ) + { + *preempted =3D true; + goto out; + } + } + + out: /* Make sure everyone sees the unshadowings */ guest_flush_tlb_mask(d, d->dirty_cpumask); } @@ -490,7 +530,7 @@ void shadow_blow_tables_per_domain(struc if ( shadow_mode_enabled(d) && domain_vcpu(d, 0) ) { paging_lock(d); - shadow_blow_tables(d); + shadow_blow_tables(d, NULL); paging_unlock(d); } } @@ -2254,7 +2294,9 @@ void shadow_teardown(struct domain *d, b * in-use pages, as _shadow_prealloc() will no longer try to reclaim p= ages * because the domain is dying. */ - shadow_blow_tables(d); + shadow_blow_tables(d, preempted); + if ( preempted && *preempted ) + goto out; =20 #if (SHADOW_OPTIMIZATIONS & (SHOPT_VIRTUAL_TLB|SHOPT_OUT_OF_SYNC)) /* Free the virtual-TLB array attached to each vcpu */ @@ -2492,7 +2534,7 @@ static int cf_check sh_enable_log_dirty( /* This domain already has some shadows: need to clear them out * of the way to make sure that all references to guest memory are * properly write-protected */ - shadow_blow_tables(d); + shadow_blow_tables(d, NULL); } =20 #if (SHADOW_OPTIMIZATIONS & SHOPT_LINUX_L3_TOPLEVEL) @@ -2530,7 +2572,7 @@ static void cf_check sh_clean_dirty_bitm /* Need to revoke write access to the domain's pages again. * In future, we'll have a less heavy-handed approach to this, * but for now, we just unshadow everything except Xen. */ - shadow_blow_tables(d); + shadow_blow_tables(d, NULL); paging_unlock(d); } =20 --- a/xen/arch/x86/mm/shadow/hvm.c +++ b/xen/arch/x86/mm/shadow/hvm.c @@ -979,7 +979,7 @@ sh_write_p2m_entry_post(struct p2m_domai again), so it doesn't matter too much. */ if ( d->arch.paging.shadow.has_fast_mmio_entries ) { - shadow_blow_tables(d); + shadow_blow_tables(d, NULL); d->arch.paging.shadow.has_fast_mmio_entries =3D false; } } @@ -1049,7 +1049,7 @@ int shadow_track_dirty_vram(struct domai * Throw away all the shadows rather than walking through them * up to nr times getting rid of mappings of each pfn. */ - shadow_blow_tables(d); + shadow_blow_tables(d, NULL); =20 gdprintk(XENLOG_INFO, "tracking VRAM %lx - %lx\n", begin_pfn, end_= pfn); =20 --- a/xen/arch/x86/mm/shadow/private.h +++ b/xen/arch/x86/mm/shadow/private.h @@ -471,7 +471,7 @@ mfn_t oos_snapshot_lookup(struct domain #endif /* (SHADOW_OPTIMIZATIONS & SHOPT_OUT_OF_SYNC) */ =20 /* Deliberately free all the memory we can: tear down all of d's shadows. = */ -void shadow_blow_tables(struct domain *d); +void shadow_blow_tables(struct domain *d, bool *preempted); =20 /* * Remove all mappings of a guest frame from the shadow tables. From nobody Wed Aug 26 01:48:52 2026 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=quarantine dis=none) header.from=suse.com ARC-Seal: i=1; a=rsa-sha256; t=1785248476; cv=none; d=zohomail.com; s=zohoarc; b=Abre08YM1OKnd9a3QM13AKCif86lsCLfUgoNeEdo3cJcPQ9zdAOjsZGDPYH16WnsEb1aeTLbB15hybFLED2PnW3V1FEC7ZIzjA9dH7P5MZGvGGIZDkbCLPs0siOTdCn1XKmmfLjDUd4Q7QmZgsWv+Gp+66WvBt0zViZtagxKbn8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785248476; 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=ZTRJOiX4KZgYvcy+AGnnd1X5rKWWENr2//PiRreu6o4=; b=gWn+kA0RMoab7cVs6Mll2pT9NerbQTyS7roeglVzVjr859KDrZW88XQ+s6vYVnVk79IKX2E13gHaIbJfkkZMwbUDWKVRWDns+C1LnPAYmWxIu9U7XVrjqu3MlF5yWaU7gLxzQQcZcb8nSfl/bzjM5PZkMoQibGyI83XmBqbf/yg= 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=quarantine dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1785248476863622.545893110115; Tue, 28 Jul 2026 07:21:16 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1374357.1621513 (Exim 4.92) (envelope-from ) id 1woifv-0001PW-M4; Tue, 28 Jul 2026 14:20:55 +0000 Received: by outflank-mailman (output) from mailman id 1374357.1621513; Tue, 28 Jul 2026 14:20:55 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1woifv-0001PP-Ib; Tue, 28 Jul 2026 14:20:55 +0000 Received: by outflank-mailman (input) for mailman id 1374357; Tue, 28 Jul 2026 14:20:54 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1woifu-0001Nv-81 for xen-devel@lists.xenproject.org; Tue, 28 Jul 2026 14:20:54 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1woift-004wIj-Cz for xen-devel@lists.xenproject.org; Tue, 28 Jul 2026 16:20:53 +0200 Received: from [10.42.69.9] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a68babd-bab6-0a2a0a5309dd-0a2a45098546-16 for ; Tue, 28 Jul 2026 16:20:53 +0200 Received: from [209.85.128.41] (helo=mail-wm1-f41.google.com) by tlsNG-bad1c0.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a68bac5-be1a-0a2a45090019-d1558029c9fd-3 for ; Tue, 28 Jul 2026 16:20:53 +0200 Received: by mail-wm1-f41.google.com with SMTP id 5b1f17b1804b1-493b966dd74so24556855e9.3 for ; Tue, 28 Jul 2026 07:20:53 -0700 (PDT) Received: from [10.156.60.236] (ip-037-024-206-209.um08.pools.vodafone-ip.de. [37.24.206.209]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4957d41ed1bsm267580865e9.2.2026.07.28.07.20.51 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 28 Jul 2026 07:20:52 -0700 (PDT) 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" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=google header.d=suse.com header.i="@suse.com" header.h="Content-Transfer-Encoding:Content-Type:In-Reply-To:Autocrypt:Content-Language:References:Cc:To:From:Subject:User-Agent:MIME-Version:Date:Message-ID" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=google; t=1785248453; x=1785853253; darn=lists.xenproject.org; h=content-transfer-encoding:content-type:in-reply-to:autocrypt :content-language:references:cc:to:from:subject:user-agent :mime-version:date:message-id:from:to:cc:subject:date:message-id :reply-to:content-type; bh=ZTRJOiX4KZgYvcy+AGnnd1X5rKWWENr2//PiRreu6o4=; b=YCZPaELsVwtbY/rdmSe1OQZ0wb6v1McG8ctdla4tlf/mNq029OzucSn1VZOL+8iZQH mQaPOIXVLUwKRt/onYvhrtak6V5I6VFIY9nzGvKvsO9XHQzZ8BQJsoMC0/KGVkd6a2Fp BxTG6bCA+ct+TeyiAwD2GvzLnBo2611qIgVC2/MsqAudmAertHJs0sAO9WtHQeoVNi4b VPqwkPWlfvwuz2XNWfXeA0grIA/vogj8pYMggWUmA1+HE+O/yLPons28f3xY+OlGDMWi t1d+OcWLu4Xz+4O1sadCshilS4OpUkaia825FyMivjG9jzqFlM7sV/SVQoIAB3G9o2oP +/Pw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785248453; x=1785853253; h=content-transfer-encoding:content-type:in-reply-to:autocrypt :content-language:references:cc:to:from:subject:user-agent :mime-version:date:message-id:x-gm-gg:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to:content-type; bh=ZTRJOiX4KZgYvcy+AGnnd1X5rKWWENr2//PiRreu6o4=; b=H7sPlbsVrNhF2jlIsRsZz1f0F+TSfd+8aKpUuBqE9buunONBG3l8uc8u/3EulfokWx FDN/shC9/Gk2qSXsu62LDPckn/UZyzDSra0eyUojGKiX18ivDoeQw0KnFxrKaR5dwbkQ OqiQ+wgUg3OgNAoMuCuEtNneTJANf9r7lLeDr0+DFf4pxzhEzQP0lrU6qyboqs9iUHcQ O4lklG03QuFiwFa/JnpTKzcXFXveZSIv5zgogM6EnJXyMAwDnjQQ9at3ZuxapCeY7jpD who3r+DpXx+z7MVroweYomj+IziaIam66FnrHsD2/Oqc5pBTj1aE8AF+9SFVDCVu7/1D G/gw== X-Gm-Message-State: AOJu0Yx1ouqi5URLRcFweBHw1ifb/3LBqBQK1gYgBrcwgef4p5puOcgK RkRtTBmcy4MPgRhly93hJqm33PAjL3FqJsnNrxMnx8oEQn8aXp2Co9r+mJq8XSuzKWJMljX08ki AKOUZjg== X-Gm-Gg: AR+sD12d/BbogeAES3wOaOercuLKICmzUpGemoOBtHx57E7NUE8iqaR2I4Vj0h9H8Xz 2j68RJZby4wjHza2u0hRo+4Q5VEQd9m6D8HMvngzfA2cCxH5yHVNl4k6FDWLy/BpHH3+uVWBwsj LhY8DP/zEQtFh8Si1ueEdQ256iDTlJxUA6RiTVGM2RBWpdqjXF4IQQgRVsZhmyOKf0szh+o3D97 cBYXzSl+s6z7MgKj7H7ydP0IThPJTNOJiiLgPocGznntsp6oSYpdd5p/9X3edXbE1zv/ZZyu+56 PJdCOsjLfANwew2zIvBh6U7dF9lBXPMNMV+6S0lrjd+4xO1bJTK6EQil5LljJZGBZFIeKnPq6uC GLWQ9xMZLh6lr910t2cCx+eNZ0LnPUSYUjBvt3R6XpZakiowzVu+dOTB5BKfCarhBrCH/qFQR8m +qmelKV9Ye+/LnNRp1lJtYO4v4bv7nlRyEPgSm6XfvAG2JIT6FruY1Ge6+hsEjjP3b5Q== X-Received: by 2002:a05:600c:1c27:b0:493:e974:41ac with SMTP id 5b1f17b1804b1-496c643c6f9mr29533425e9.16.1785248452602; Tue, 28 Jul 2026 07:20:52 -0700 (PDT) Message-ID: <75dede35-643c-4deb-a50f-f0291b96aa2c@suse.com> Date: Tue, 28 Jul 2026 16:20:51 +0200 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: [PATCH v15 02/10] x86/shadow: blow away tables first when tearing down From: Jan Beulich To: "xen-devel@lists.xenproject.org" Cc: Andrew Cooper , Tim Deegan References: <68c16600-a4bf-4060-a1fc-56c4ae655b03@suse.com> Content-Language: en-US Autocrypt: addr=jbeulich@suse.com; keydata= xsDiBFk3nEQRBADAEaSw6zC/EJkiwGPXbWtPxl2xCdSoeepS07jW8UgcHNurfHvUzogEq5xk hu507c3BarVjyWCJOylMNR98Yd8VqD9UfmX0Hb8/BrA+Hl6/DB/eqGptrf4BSRwcZQM32aZK 7Pj2XbGWIUrZrd70x1eAP9QE3P79Y2oLrsCgbZJfEwCgvz9JjGmQqQkRiTVzlZVCJYcyGGsD /0tbFCzD2h20ahe8rC1gbb3K3qk+LpBtvjBu1RY9drYk0NymiGbJWZgab6t1jM7sk2vuf0Py O9Hf9XBmK0uE9IgMaiCpc32XV9oASz6UJebwkX+zF2jG5I1BfnO9g7KlotcA/v5ClMjgo6Gl MDY4HxoSRu3i1cqqSDtVlt+AOVBJBACrZcnHAUSuCXBPy0jOlBhxPqRWv6ND4c9PH1xjQ3NP nxJuMBS8rnNg22uyfAgmBKNLpLgAGVRMZGaGoJObGf72s6TeIqKJo/LtggAS9qAUiuKVnygo 3wjfkS9A3DRO+SpU7JqWdsveeIQyeyEJ/8PTowmSQLakF+3fote9ybzd880fSmFuIEJldWxp Y2ggPGpiZXVsaWNoQHN1c2UuY29tPsJgBBMRAgAgBQJZN5xEAhsDBgsJCAcDAgQVAggDBBYC AwECHgECF4AACgkQoDSui/t3IH4J+wCfQ5jHdEjCRHj23O/5ttg9r9OIruwAn3103WUITZee e7Sbg12UgcQ5lv7SzsFNBFk3nEQQCACCuTjCjFOUdi5Nm244F+78kLghRcin/awv+IrTcIWF hUpSs1Y91iQQ7KItirz5uwCPlwejSJDQJLIS+QtJHaXDXeV6NI0Uef1hP20+y8qydDiVkv6l IreXjTb7DvksRgJNvCkWtYnlS3mYvQ9NzS9PhyALWbXnH6sIJd2O9lKS1Mrfq+y0IXCP10eS FFGg+Av3IQeFatkJAyju0PPthyTqxSI4lZYuJVPknzgaeuJv/2NccrPvmeDg6Coe7ZIeQ8Yj t0ARxu2xytAkkLCel1Lz1WLmwLstV30g80nkgZf/wr+/BXJW/oIvRlonUkxv+IbBM3dX2OV8 AmRv1ySWPTP7AAMFB/9PQK/VtlNUJvg8GXj9ootzrteGfVZVVT4XBJkfwBcpC/XcPzldjv+3 HYudvpdNK3lLujXeA5fLOH+Z/G9WBc5pFVSMocI71I8bT8lIAzreg0WvkWg5V2WZsUMlnDL9 mpwIGFhlbM3gfDMs7MPMu8YQRFVdUvtSpaAs8OFfGQ0ia3LGZcjA6Ik2+xcqscEJzNH+qh8V m5jjp28yZgaqTaRbg3M/+MTbMpicpZuqF4rnB0AQD12/3BNWDR6bmh+EkYSMcEIpQmBM51qM EKYTQGybRCjpnKHGOxG0rfFY1085mBDZCH5Kx0cl0HVJuQKC+dV2ZY5AqjcKwAxpE75MLFkr wkkEGBECAAkFAlk3nEQCGwwACgkQoDSui/t3IH7nnwCfcJWUDUFKdCsBH/E5d+0ZnMQi+G0A nAuWpQkjM1ASeQwSHEeAWPgskBQL In-Reply-To: <68c16600-a4bf-4060-a1fc-56c4ae655b03@suse.com> Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-bad1c0/1785248453-FC817034-6B0A6AA9/0/0 X-purgate-type: clean X-purgate-size: 1670 X-ZohoMail-DKIM: pass (identity @suse.com) X-ZM-MESSAGEID: 1785248478316158502 With shadow_blow_tables() but not sh_detach_old_tables() (called by shadow_vcpu_teardown()) being preemptable, move the invocation of the former ahead. This way future finer grained preemption checks applied to shadow_blow_tables() will further benefit teardown behavior. Signed-off-by: Jan Beulich Acked-by: Roger Pau Monn=C3=A9 --- v13: New. --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -2279,6 +2279,17 @@ void shadow_teardown(struct domain *d, b ASSERT(d->is_dying); ASSERT(d !=3D current->domain); =20 + /* + * Reclaim all shadow memory so that shadow_set_allocation() doesn't f= ind + * in-use pages, as _shadow_prealloc() will no longer try to reclaim p= ages + * because the domain is dying. + */ + paging_lock(d); + shadow_blow_tables(d, preempted); + paging_unlock(d); + if ( preempted && *preempted ) + return; + /* TODO - Remove when the teardown path is better structured. */ for_each_vcpu ( d, v ) shadow_vcpu_teardown(v); @@ -2289,15 +2300,6 @@ void shadow_teardown(struct domain *d, b =20 paging_lock(d); =20 - /* - * Reclaim all shadow memory so that shadow_set_allocation() doesn't f= ind - * in-use pages, as _shadow_prealloc() will no longer try to reclaim p= ages - * because the domain is dying. - */ - shadow_blow_tables(d, preempted); - if ( preempted && *preempted ) - goto out; - #if (SHADOW_OPTIMIZATIONS & (SHOPT_VIRTUAL_TLB|SHOPT_OUT_OF_SYNC)) /* Free the virtual-TLB array attached to each vcpu */ for_each_vcpu(d, v) From nobody Wed Aug 26 01:48:52 2026 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=quarantine dis=none) header.from=suse.com ARC-Seal: i=1; a=rsa-sha256; t=1785248500; cv=none; d=zohomail.com; s=zohoarc; b=JchcYiVYXp3lGBBHuWboUlcIdppZUceIgHwpmdEIIg6XilO8/2o/3kT9svWOdYVPKw1w2VZBr3tfPPGyYwZV6+lHh2dsNAhIBcw2grt639sJQglJZZj3JZbYmHmj6KkwlNS4MvuioJQx7gfn2ZnjP9oORRnsreCc7p8uYROJHM0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785248500; 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=XGrZ7kjDuuGJhwYMCufypln4dXhKBUUO4NDiLthgxi8=; b=NH5nZrCN/Zp1RsiXzYzPIjrzQvVQTFgzKnYFMy/scD6xaAk3Th/DJrhBfM56fvEgPiZ84wTC/gkrAqNAK/uqqjpojwDZuYIcgjK9QZgrF/pV8K3vy4lHR9pwEGCkpVdzjCdDtmD0SqnDcHTeHtZYECbNkZKyY3ub9GtZGqjgRdU= 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=quarantine dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1785248500157266.7439643960878; Tue, 28 Jul 2026 07:21:40 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1374368.1621522 (Exim 4.92) (envelope-from ) id 1woigR-0001ys-S5; Tue, 28 Jul 2026 14:21:27 +0000 Received: by outflank-mailman (output) from mailman id 1374368.1621522; Tue, 28 Jul 2026 14:21:27 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1woigR-0001yl-PU; Tue, 28 Jul 2026 14:21:27 +0000 Received: by outflank-mailman (input) for mailman id 1374368; Tue, 28 Jul 2026 14:21:26 +0000 Received: from mx.expurgate.net ([194.145.224.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1woigQ-0001yQ-5F for xen-devel@lists.xenproject.org; Tue, 28 Jul 2026 14:21:26 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1woigP-00HNbQ-HT for xen-devel@lists.xenproject.org; Tue, 28 Jul 2026 16:21:25 +0200 Received: from [10.42.69.7] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a68bada-2eae-0a2a0a5409dd-0a2a45079dd6-16 for ; Tue, 28 Jul 2026 16:21:25 +0200 Received: from [209.85.128.46] (helo=mail-wm1-f46.google.com) by tlsNG-ef75cf.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a68bae5-b4ea-0a2a45070019-d155802eec42-3 for ; Tue, 28 Jul 2026 16:21:25 +0200 Received: by mail-wm1-f46.google.com with SMTP id 5b1f17b1804b1-4954dff6536so27595185e9.0 for ; Tue, 28 Jul 2026 07:21:25 -0700 (PDT) Received: from [10.156.60.236] (ip-037-024-206-209.um08.pools.vodafone-ip.de. [37.24.206.209]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-496c45bb2e7sm86149115e9.7.2026.07.28.07.21.23 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 28 Jul 2026 07:21:23 -0700 (PDT) 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" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=google header.d=suse.com header.i="@suse.com" header.h="Content-Transfer-Encoding:Content-Type:In-Reply-To:Autocrypt:Content-Language:References:Cc:To:From:Subject:User-Agent:MIME-Version:Date:Message-ID" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=google; t=1785248485; x=1785853285; darn=lists.xenproject.org; h=content-transfer-encoding:content-type:in-reply-to:autocrypt :content-language:references:cc:to:from:subject:user-agent :mime-version:date:message-id:from:to:cc:subject:date:message-id :reply-to:content-type; bh=XGrZ7kjDuuGJhwYMCufypln4dXhKBUUO4NDiLthgxi8=; b=ftyQmVeqX169mLpt97B/WrV/L/NfbYVN5giGjkVhncNOqDILD1ArFajOzJDgt3LGtz l2J5uEqZivRfV8reifxCkTtTvBC+oWhtn6Vn8D8A4S79qEtPZov1TMaCLIOjuGYo4BpD ++vh99DrHYvg2VZf9Ok97baUNmKpAxrsOFsSjzv3F5l3nbrheKCbm1sswBfSqlbd94to VoPX8dmsWNaG64ovM12sqIllnaOwBUTx1kzgrbgYkBA5/DOmRkAAMVEIDGCS1UE7s1ke ZrQBTYJ6jbstTisWTijS/19QlR+B1xBlkDVdIaQgQJppbmiyj2iUnx/ingb/9WOo4oRP 4brg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785248485; x=1785853285; h=content-transfer-encoding:content-type:in-reply-to:autocrypt :content-language:references:cc:to:from:subject:user-agent :mime-version:date:message-id:x-gm-gg:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to:content-type; bh=XGrZ7kjDuuGJhwYMCufypln4dXhKBUUO4NDiLthgxi8=; b=OP0VwMQNI2+tEi4/jMuOgdIVip/K5uj7D73kuFcvpf3vSWCVIJZXDoB62vLrkqu6A2 teyC5PcpmVhA1UXPaeeeNT06rQN8VnNsgfSVd0/4alklMm950XNp7BvjbzYf79PSSm6o onoRLD2KKlAG/vQaV/zuZk8o5f37i9Iu2UZ2ie4micmJrx3jzEEjv45tXqPc2iQp4M5u JhaTjN23hOrdYJ1UgdHxNhJIbOfy7KEVnxugMVgSCyXmPno3rVfyi9cbGf7CPRE7TORP OSTkVSx2PEzFq5SobrFiQ2iDjY4InnTJqYq9fDJ2+nNK393Z5UHl9cxU4aLVAUZkWMMa ERAQ== X-Gm-Message-State: AOJu0Yy/wPvWEFIY5u/zNSGMwciVAPglG5/w36rK//zrh3uUsTMK2Pf6 W9eJxVFjvsEmtTFj2DP2JL0fEmHdLKAUYw9rgsmbnjMDvhKdTTuSMgMlKhbw6uUuNwfPxM5Xa9F tjmCo5w== X-Gm-Gg: AR+sD12yjaZf9DeTuihhduD1TSUNZaThFV9XCiaLO+610nUTFTOdwq/N2GcTJKYOHis yllasjXphj8ISnApL2CqD5/BI1QumX7BGkDrvjd56vxT2x7XY43UDi/GbkXuoBhiVGH9fsx17U4 Q/CXQ9TNF8OCtZr+JpDhBCtnwgrO+yxVANlaXBZNkv1vEnkiWC+i6DuTmiuC8gE9JXjgR1FF0JE hhFXpqfwxEzCC7J8kRXsZiLddqs0/9g+rn4I0tfG7J/MbbLXA6ve1a9j/wOXQBaWEHv3uF03HzY D1/GkEa+YluVVrFsQjnyOqC3Z9CuVXQBpPpV+EyB6Am9G3y4fOHLWR/hF0Ey3FMptqKVZD4icHk p8+lZ1UrmyF82H+JRYd47Rh7ssfahiFsVAuzKEnmaVfbXW39a6h4Hzcc7HnBmyT2lXAB/++4mhd 44/98Su+oY/uCpOFHl3wTkOPHtgilchp+4kFTyZQ0rbipMoIXUK3AThWiVvYNW9waUJg== X-Received: by 2002:a05:600c:5291:b0:495:4e1d:82e6 with SMTP id 5b1f17b1804b1-496c659294bmr28684895e9.36.1785248484901; Tue, 28 Jul 2026 07:21:24 -0700 (PDT) Message-ID: <4ba9dcd7-3e96-4ced-bafb-8bfb35fe26ca@suse.com> Date: Tue, 28 Jul 2026 16:21:22 +0200 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: [PATCH v15 03/10] x86/shadow: 1-bit-disable doesn't need to detach old tables From: Jan Beulich To: "xen-devel@lists.xenproject.org" Cc: Andrew Cooper , Tim Deegan References: <68c16600-a4bf-4060-a1fc-56c4ae655b03@suse.com> Content-Language: en-US Autocrypt: addr=jbeulich@suse.com; keydata= xsDiBFk3nEQRBADAEaSw6zC/EJkiwGPXbWtPxl2xCdSoeepS07jW8UgcHNurfHvUzogEq5xk hu507c3BarVjyWCJOylMNR98Yd8VqD9UfmX0Hb8/BrA+Hl6/DB/eqGptrf4BSRwcZQM32aZK 7Pj2XbGWIUrZrd70x1eAP9QE3P79Y2oLrsCgbZJfEwCgvz9JjGmQqQkRiTVzlZVCJYcyGGsD /0tbFCzD2h20ahe8rC1gbb3K3qk+LpBtvjBu1RY9drYk0NymiGbJWZgab6t1jM7sk2vuf0Py O9Hf9XBmK0uE9IgMaiCpc32XV9oASz6UJebwkX+zF2jG5I1BfnO9g7KlotcA/v5ClMjgo6Gl MDY4HxoSRu3i1cqqSDtVlt+AOVBJBACrZcnHAUSuCXBPy0jOlBhxPqRWv6ND4c9PH1xjQ3NP nxJuMBS8rnNg22uyfAgmBKNLpLgAGVRMZGaGoJObGf72s6TeIqKJo/LtggAS9qAUiuKVnygo 3wjfkS9A3DRO+SpU7JqWdsveeIQyeyEJ/8PTowmSQLakF+3fote9ybzd880fSmFuIEJldWxp Y2ggPGpiZXVsaWNoQHN1c2UuY29tPsJgBBMRAgAgBQJZN5xEAhsDBgsJCAcDAgQVAggDBBYC AwECHgECF4AACgkQoDSui/t3IH4J+wCfQ5jHdEjCRHj23O/5ttg9r9OIruwAn3103WUITZee e7Sbg12UgcQ5lv7SzsFNBFk3nEQQCACCuTjCjFOUdi5Nm244F+78kLghRcin/awv+IrTcIWF hUpSs1Y91iQQ7KItirz5uwCPlwejSJDQJLIS+QtJHaXDXeV6NI0Uef1hP20+y8qydDiVkv6l IreXjTb7DvksRgJNvCkWtYnlS3mYvQ9NzS9PhyALWbXnH6sIJd2O9lKS1Mrfq+y0IXCP10eS FFGg+Av3IQeFatkJAyju0PPthyTqxSI4lZYuJVPknzgaeuJv/2NccrPvmeDg6Coe7ZIeQ8Yj t0ARxu2xytAkkLCel1Lz1WLmwLstV30g80nkgZf/wr+/BXJW/oIvRlonUkxv+IbBM3dX2OV8 AmRv1ySWPTP7AAMFB/9PQK/VtlNUJvg8GXj9ootzrteGfVZVVT4XBJkfwBcpC/XcPzldjv+3 HYudvpdNK3lLujXeA5fLOH+Z/G9WBc5pFVSMocI71I8bT8lIAzreg0WvkWg5V2WZsUMlnDL9 mpwIGFhlbM3gfDMs7MPMu8YQRFVdUvtSpaAs8OFfGQ0ia3LGZcjA6Ik2+xcqscEJzNH+qh8V m5jjp28yZgaqTaRbg3M/+MTbMpicpZuqF4rnB0AQD12/3BNWDR6bmh+EkYSMcEIpQmBM51qM EKYTQGybRCjpnKHGOxG0rfFY1085mBDZCH5Kx0cl0HVJuQKC+dV2ZY5AqjcKwAxpE75MLFkr wkkEGBECAAkFAlk3nEQCGwwACgkQoDSui/t3IH7nnwCfcJWUDUFKdCsBH/E5d+0ZnMQi+G0A nAuWpQkjM1ASeQwSHEeAWPgskBQL In-Reply-To: <68c16600-a4bf-4060-a1fc-56c4ae655b03@suse.com> Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-ef75cf/1785248485-A54C3AE4-A87BD2E7/0/0 X-purgate-type: clean X-purgate-size: 2608 X-ZohoMail-DKIM: pass (identity @suse.com) X-ZM-MESSAGEID: 1785248502598158500 Just ahead of the loop being modified sh_new_mode() is called, which in turn calls sh_update_paging_modes() and thus sh_detach_old_tables(). To retain the intended effect of not leaving any shadows in place, avoid re-establishing a new top-level shadow from sh_update_paging_modes(). Signed-off-by: Jan Beulich Acked-by: Roger Pau Monn=C3=A9 --- This doesn't need to be part of the XSA, but it eliminates one point of concern wrt preemption checking. However, in the context of "x86/mm: make more of log-dirty mode enable/disable preemptable" I started wondering whether things don't want doing differently. 1-bit-enables technically don't need to purge all shadows: - log-dirty enable only needs to get rid of all L1 entries; this could be done via hash lookup (of all L1/FL1 shadows) instead of shadow_blow_tables(), - test enable doesn't need any purging; it may be the intention though that it does a certain amount of purging, - force enable doesn't need to do any purging either. We could therefore pass a new boolean through sh_new_mode() to sh_update_paging_modes() to suppress the call to sh_detach_old_tables() for some (all?) of the 1-bit enables. 1-bit disables (log-dirty as well as test) match the above, but of course they will need to (at least) detach all tables when shadow mode is being turned off altogether (i.e. the very invocation that's being deleted here). As done in the other patch, the amount of work to do by the (then possibly retained) sh_detach_old_tables() here could be bounded by "preparatory" purging (in a properly preemptable way) in shadow_one_bit_disable() or its callers. Using shadow_blow_tables() for that purpose is probably preferable anyway, as sh_detach_old_tables() alone won't get rid of pinned shadows. --- v15: Re-base. v13: New. --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -1982,7 +1982,8 @@ static void sh_update_paging_modes(struc } #endif /* OOS */ =20 - v->arch.paging.mode->update_cr3(v, false); + if ( paging_mode_enabled(d) ) + v->arch.paging.mode->update_cr3(v, false); } =20 /* @@ -2459,8 +2460,6 @@ static int shadow_one_bit_disable(struct d->arch.paging.free_pages, d->arch.paging.p2m_pages= ); for_each_vcpu(d, v) { - if ( v->arch.paging.mode ) - sh_detach_old_tables(v); if ( !(v->arch.flags & TF_kernel_mode) ) make_cr3(v, pagetable_get_mfn(v->arch.guest_table_user)); else From nobody Wed Aug 26 01:48:52 2026 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=quarantine dis=none) header.from=suse.com ARC-Seal: i=1; a=rsa-sha256; t=1785248525; cv=none; d=zohomail.com; s=zohoarc; b=M3xGQzeqSfvxMSZwE/+IUvUe9N6VOGAsyQV5tDTQ4QYzEvQDQ05CerDG2XKd/+1+QTChLV1cphbPzvO3plICZtd8jLlC3vyIqd/U5uQZSqp4n7hvVGIxlEi6IoobTALsbgOmXnidqh4K/cjs7eyME0jFvWIJBykpv1IHDe2FZ/U= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785248525; 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=HR0du3EiXgBA3rCKAKjjBRbHCVyWjla1ikrTdisIkS0=; b=QzCbOeLgz4pUzvGXWtoSVYw9ypn9Z5csrypBSS52NXc0ag7qMY/Pmx6WtLzIzOqMZ2On087wA+ShJscJICK5nYoVU5W3uupjkKQusg8g4MHU4BBs3n/oDkHiBw91M+7kxNVfrcpHxMSLQ9jJhPbtLEYEu/y/dFyCj5hia69h4Xc= 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=quarantine dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1785248525827317.2627441776888; Tue, 28 Jul 2026 07:22:05 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1374374.1621531 (Exim 4.92) (envelope-from ) id 1woigo-0002Qm-2x; Tue, 28 Jul 2026 14:21:50 +0000 Received: by outflank-mailman (output) from mailman id 1374374.1621531; Tue, 28 Jul 2026 14:21:50 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1woigo-0002QK-07; Tue, 28 Jul 2026 14:21:50 +0000 Received: by outflank-mailman (input) for mailman id 1374374; Tue, 28 Jul 2026 14:21:49 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1woigm-0002P6-Tg for xen-devel@lists.xenproject.org; Tue, 28 Jul 2026 14:21:49 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1woigm-004wxv-AA for xen-devel@lists.xenproject.org; Tue, 28 Jul 2026 16:21:48 +0200 Received: from [10.42.69.2] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a68baf8-bab6-0a2a0a5309dd-0a2a45029302-24 for ; Tue, 28 Jul 2026 16:21:48 +0200 Received: from [209.85.128.50] (helo=mail-wm1-f50.google.com) by tlsNG-720697.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a68bafb-6ca4-0a2a45020019-d1558032f181-3 for ; Tue, 28 Jul 2026 16:21:47 +0200 Received: by mail-wm1-f50.google.com with SMTP id 5b1f17b1804b1-49548aebcd8so29200925e9.3 for ; Tue, 28 Jul 2026 07:21:47 -0700 (PDT) Received: from [10.156.60.236] (ip-037-024-206-209.um08.pools.vodafone-ip.de. [37.24.206.209]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4957bfd1a60sm303699545e9.2.2026.07.28.07.21.46 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 28 Jul 2026 07:21:46 -0700 (PDT) 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" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=google header.d=suse.com header.i="@suse.com" header.h="Content-Transfer-Encoding:Content-Type:In-Reply-To:Autocrypt:Content-Language:References:Cc:To:From:Subject:User-Agent:MIME-Version:Date:Message-ID" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=google; t=1785248507; x=1785853307; darn=lists.xenproject.org; h=content-transfer-encoding:content-type:in-reply-to:autocrypt :content-language:references:cc:to:from:subject:user-agent :mime-version:date:message-id:from:to:cc:subject:date:message-id :reply-to:content-type; bh=HR0du3EiXgBA3rCKAKjjBRbHCVyWjla1ikrTdisIkS0=; b=VHQI0kDr/crno7tTBYcG70oEP8dGoq5/1NAbaNx159eRupoToGkJItn7BwMxmhDItq uFLxsQsd45RjxGj16HjYVWmV+K9aCn55wZ5ivRciWaSI3SCjETuNbLPC90lV9iyNUy+8 Ac6J/qmTM90Y6Ee6ws+fn+fWOc6RaeHLQ/5esOngODESDY4LG+4CWk9gFaK49agiCW7w EspnMLKMKskAebCtuE66/Gf+hLSlgAbHLuMF/EiZldbcL9CO+cKG++WZnoBNIBNh8H4y QfvmsivwUHPLqCrOET3Y+A9/cjPWv9emT/2p2298LNWqo7BBjvg/KhkwXhbcuxpkxHkd BCaw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785248507; x=1785853307; h=content-transfer-encoding:content-type:in-reply-to:autocrypt :content-language:references:cc:to:from:subject:user-agent :mime-version:date:message-id:x-gm-gg:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to:content-type; bh=HR0du3EiXgBA3rCKAKjjBRbHCVyWjla1ikrTdisIkS0=; b=bGOTuyAV+znArdFhVFn/IZ6UJrOgg8al+3cRGmGT+5nhu8rYWSxNM4nebCFYjTZbh6 Lsc+YsCTHt7A2894xIAJdiOTP1ZJku+xluuVAybCwIVvIT67fn8M6t6VFLQUM3f52Y3j ay8nkEH6I+2wUG4plLFf7QIv3wAmuVs0UKl0JJy2HMsOlbpENBHBTL2O1/mVnOEmhqRN ysX9erhtUn8e5OlVEeJegXbJyEcMCey66AME8RkD+sQ/eP/xGFOkm1ofYKGKDd0ESl2b sRwL5uDm9Ex79oyt52l7aexRMa3RwPDRl6h/2gJVj7rl0ZBuYvcsaj3bup+ZOtUukJMq Icog== X-Gm-Message-State: AOJu0YwXpngP1ikogK8BoGdHor4Gx7cLL+QPwzkzob4cTXi5NKwOw7As IHhz8nwb0Mh1uA68oRE4mB9oARf+m76wNJvOOCHVUFWOJhI/7SRtmYsFkw7E8MFEpP92GclYT3m Oo53iqQ== X-Gm-Gg: AR+sD10tZ+rSkZnkFhqsMItP2ueEqRqdh7O6gJjJiAleDe7lTK6A66Ubrh/CEAum6V+ f/+D8GV+RVFU3m04yNq3/ukyOBpMtJKj2Bb8GzLg+/Lt/yn/7RZ3OqbcvalNFGWCVsY4GlWeR/N X2FwMpwz+yFaMR8RYdz2TFcOImPcITt8wB00TuJQPdAhAN09Vb220+FsRvfTNZ8DhzdlQjFGkLC JmxOsBqFTr5Y+FmpacFLacylybwAAGpyy4vSZ1XiAjW9jgxB0zgZOq9MHbNi2fWdAHU+r91fWk+ mpKpjSftseTRnUiBizBmXTJNjBWpAtkZYMZHhUBmojX4LcaQDgqnaBxoQ3rn8wZT+g3MaxPGpe+ vRBcDKr9s5F3lN7RMtDzDVrlYtQEKxUGenJX0BZBolCRQ9ESnTUHOvpyEF3WgA/IZhph06+WMTv Tdv10AvK2S8T4Fz3ufeQR9uRe4R//S/tV3FGMqBUFeDqYdh5JocBsJ0XNVo7k2wD90ONI0T22uC wcW X-Received: by 2002:a05:600c:3144:b0:496:b39f:1a03 with SMTP id 5b1f17b1804b1-496c64261fdmr29994245e9.5.1785248507153; Tue, 28 Jul 2026 07:21:47 -0700 (PDT) Message-ID: Date: Tue, 28 Jul 2026 16:21:45 +0200 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: [PATCH v15 04/10] x86/shadow: reduce amount of work to do by shadow_unhook_mappings() From: Jan Beulich To: "xen-devel@lists.xenproject.org" Cc: Andrew Cooper , Tim Deegan References: <68c16600-a4bf-4060-a1fc-56c4ae655b03@suse.com> Content-Language: en-US Autocrypt: addr=jbeulich@suse.com; keydata= xsDiBFk3nEQRBADAEaSw6zC/EJkiwGPXbWtPxl2xCdSoeepS07jW8UgcHNurfHvUzogEq5xk hu507c3BarVjyWCJOylMNR98Yd8VqD9UfmX0Hb8/BrA+Hl6/DB/eqGptrf4BSRwcZQM32aZK 7Pj2XbGWIUrZrd70x1eAP9QE3P79Y2oLrsCgbZJfEwCgvz9JjGmQqQkRiTVzlZVCJYcyGGsD /0tbFCzD2h20ahe8rC1gbb3K3qk+LpBtvjBu1RY9drYk0NymiGbJWZgab6t1jM7sk2vuf0Py O9Hf9XBmK0uE9IgMaiCpc32XV9oASz6UJebwkX+zF2jG5I1BfnO9g7KlotcA/v5ClMjgo6Gl MDY4HxoSRu3i1cqqSDtVlt+AOVBJBACrZcnHAUSuCXBPy0jOlBhxPqRWv6ND4c9PH1xjQ3NP nxJuMBS8rnNg22uyfAgmBKNLpLgAGVRMZGaGoJObGf72s6TeIqKJo/LtggAS9qAUiuKVnygo 3wjfkS9A3DRO+SpU7JqWdsveeIQyeyEJ/8PTowmSQLakF+3fote9ybzd880fSmFuIEJldWxp Y2ggPGpiZXVsaWNoQHN1c2UuY29tPsJgBBMRAgAgBQJZN5xEAhsDBgsJCAcDAgQVAggDBBYC AwECHgECF4AACgkQoDSui/t3IH4J+wCfQ5jHdEjCRHj23O/5ttg9r9OIruwAn3103WUITZee e7Sbg12UgcQ5lv7SzsFNBFk3nEQQCACCuTjCjFOUdi5Nm244F+78kLghRcin/awv+IrTcIWF hUpSs1Y91iQQ7KItirz5uwCPlwejSJDQJLIS+QtJHaXDXeV6NI0Uef1hP20+y8qydDiVkv6l IreXjTb7DvksRgJNvCkWtYnlS3mYvQ9NzS9PhyALWbXnH6sIJd2O9lKS1Mrfq+y0IXCP10eS FFGg+Av3IQeFatkJAyju0PPthyTqxSI4lZYuJVPknzgaeuJv/2NccrPvmeDg6Coe7ZIeQ8Yj t0ARxu2xytAkkLCel1Lz1WLmwLstV30g80nkgZf/wr+/BXJW/oIvRlonUkxv+IbBM3dX2OV8 AmRv1ySWPTP7AAMFB/9PQK/VtlNUJvg8GXj9ootzrteGfVZVVT4XBJkfwBcpC/XcPzldjv+3 HYudvpdNK3lLujXeA5fLOH+Z/G9WBc5pFVSMocI71I8bT8lIAzreg0WvkWg5V2WZsUMlnDL9 mpwIGFhlbM3gfDMs7MPMu8YQRFVdUvtSpaAs8OFfGQ0ia3LGZcjA6Ik2+xcqscEJzNH+qh8V m5jjp28yZgaqTaRbg3M/+MTbMpicpZuqF4rnB0AQD12/3BNWDR6bmh+EkYSMcEIpQmBM51qM EKYTQGybRCjpnKHGOxG0rfFY1085mBDZCH5Kx0cl0HVJuQKC+dV2ZY5AqjcKwAxpE75MLFkr wkkEGBECAAkFAlk3nEQCGwwACgkQoDSui/t3IH7nnwCfcJWUDUFKdCsBH/E5d+0ZnMQi+G0A nAuWpQkjM1ASeQwSHEeAWPgskBQL In-Reply-To: <68c16600-a4bf-4060-a1fc-56c4ae655b03@suse.com> Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-720697/1785248508-F2AB52AC-C9910AD6/0/0 X-purgate-type: clean X-purgate-size: 10127 X-ZohoMail-DKIM: pass (identity @suse.com) X-ZM-MESSAGEID: 1785248526553158500 Content-Type: text/plain; charset="utf-8" When preemption is enabled for uses of shadow_blow_tables(), the granularity of preemption checks in both of the present two passes can be pretty coarse, as deep table hierarchies may need processing. Reduce shadow page table depth up front by introducing a third (earlier) pass processing first L2, then L3 tables by doing hash lookups instead of tree traversal. Signed-off-by: Jan Beulich --- The way need for preemption is being checked for is crude, but the least intrusive variant I could think of while still respecting hash_foreach() not permitting further traversal after a removal from the hash. I've deliberately chosen 0 as the "wildcard", as using INVALID_MFN looks somewhat more fragile/risky to me. Of course we might consider introducing WILDCARD_MFN, which then could be non-zero but still distinct from INVALID_MFN. I've further deliberately made hash_foreach() return "int", not "bool", since at least transiently I was also playing with returning -ERESTART from some of the callback functions. We could avoid the hash walk for guests which never entered 64-bit mode. That would require tracking the maximum shadow paging level that was ever used (perhaps since the last [completed] shadow_blow_tables()) by a domain. (This would similarly apply to future 5-level support, where we could avoid the SHF_L4_ANY walk for guests never having entered 5-level mode.) The same may want (need) adding to _shadow_prealloc() and perhaps elsewhere. However, for zapping entries from alive domains hash lookup pulling most recently used entries to the front means most recently used entries would then also be zapped first, which isn't very nice. --- v14: Exclude 32-bit L2 types. Re-base. v13: New. --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -268,6 +268,32 @@ sh_validate_guest_entry(struct vcpu *v, return result; } =20 +typedef int (*hash_callback_t)(struct domain *d, mfn_t smfn, mfn_t other_m= fn); + +#define HASH_CALLBACKS_CHECK(mask) \ + BUILD_BUG_ON((mask) > (1U << ARRAY_SIZE(callbacks)) - 1) + +static int hash_foreach(struct domain *d, + unsigned int callback_mask, + const hash_callback_t callbacks[], + mfn_t callback_mfn); + +/* + * Dispatch table for getting per-type functions: each level must + * be called with the function to remove a lower-level shadow. + */ +static const hash_callback_t remove_callbacks[SH_type_unused] =3D { +#ifdef CONFIG_HVM + [SH_type_l2_32_shadow] =3D SHADOW_INTERNAL_NAME(sh_remove_l1_shadow, 2= ), + [SH_type_l2_pae_shadow] =3D SHADOW_INTERNAL_NAME(sh_remove_l1_shadow, = 3), +#endif + [SH_type_l2_64_shadow] =3D SHADOW_INTERNAL_NAME(sh_remove_l1_shadow, 4= ), +#ifdef CONFIG_PV32 + [SH_type_l2h_64_shadow] =3D SHADOW_INTERNAL_NAME(sh_remove_l1_shadow, = 4), +#endif + [SH_type_l3_64_shadow] =3D SHADOW_INTERNAL_NAME(sh_remove_l2_shadow, 4= ), + [SH_type_l4_64_shadow] =3D SHADOW_INTERNAL_NAME(sh_remove_l3_shadow, 4= ), +}; =20 /*************************************************************************= */ /* Memory management for shadow pages. */ @@ -476,7 +502,35 @@ void shadow_blow_tables(struct domain *d if ( !d->vcpu[0] ) return; =20 - /* Pass one: unpin all pinned pages */ + /* First pass: reduce page table depth */ + if ( preempted ) + { +#define callbacks remove_callbacks + static const unsigned int masks[] =3D { + SHF_L2_ANY & ~(SHF_L2_32 | SHF_L2_PAE), + SHF_L3_ANY, +#if CONFIG_PAGING_LEVELS > 4 + SHF_L4_ANY, +#endif + }; + + HASH_CALLBACKS_CHECK(SHF_page_type_mask & ~(SHF_L1_ANY | SHF_FL1_A= NY)); + + for ( i =3D 0; i < ARRAY_SIZE(masks); ++i ) + { + while ( hash_foreach(d, masks[i], callbacks, _mfn(0)) ) + { + if ( general_preempt_check() ) + { + *preempted =3D true; + return; + } + } + } +#undef callbacks + } + + /* Second pass: unpin all pinned pages */ foreach_pinned_shadow(d, sp, t) { smfn =3D page_to_mfn(sp); @@ -488,7 +542,7 @@ void shadow_blow_tables(struct domain *d } } =20 - /* Second pass: unhook entries of in-use shadows */ + /* Third pass: unhook entries of in-use shadows */ for_each_vcpu(d, v) for ( i =3D 0; i < ARRAY_SIZE(v->arch.paging.shadow.shadow_table);= i++ ) if ( !pagetable_is_null(v->arch.paging.shadow.shadow_table[i])= ) @@ -1151,15 +1205,10 @@ bool shadow_hash_delete(struct domain *d return true; } =20 -typedef int (*hash_callback_t)(struct domain *d, mfn_t smfn, mfn_t other_m= fn); - -#define HASH_CALLBACKS_CHECK(mask) \ - BUILD_BUG_ON((mask) > (1U << ARRAY_SIZE(callbacks)) - 1) - -static void hash_foreach(struct domain *d, - unsigned int callback_mask, - const hash_callback_t callbacks[], - mfn_t callback_mfn) +static int hash_foreach(struct domain *d, + unsigned int callback_mask, + const hash_callback_t callbacks[], + mfn_t callback_mfn) /* Walk the hash table looking at the types of the entries and * calling the appropriate callback function for each entry. * The mask determines which shadow types we call back for, and the array @@ -1176,7 +1225,7 @@ static void hash_foreach(struct domain * =20 /* Can be called via p2m code &c after shadow teardown. */ if ( unlikely(!d->arch.paging.shadow.hash_table) ) - return; + return 0; =20 /* Say we're here, to stop hash-lookups reordering the chains */ ASSERT(d->arch.paging.shadow.hash_walking =3D=3D 0); @@ -1201,6 +1250,8 @@ static void hash_foreach(struct domain * if ( done ) break; } d->arch.paging.shadow.hash_walking =3D 0; + + return done; } =20 =20 @@ -1640,21 +1691,6 @@ void sh_remove_shadows(struct domain *d, mfn_t smfn; unsigned char t; =20 - /* Dispatch table for getting per-type functions: each level must - * be called with the function to remove a lower-level shadow. */ - static const hash_callback_t callbacks[SH_type_unused] =3D { -#ifdef CONFIG_HVM - [SH_type_l2_32_shadow] =3D SHADOW_INTERNAL_NAME(sh_remove_l1_shado= w, 2), - [SH_type_l2_pae_shadow] =3D SHADOW_INTERNAL_NAME(sh_remove_l1_shad= ow, 3), -#endif - [SH_type_l2_64_shadow] =3D SHADOW_INTERNAL_NAME(sh_remove_l1_shado= w, 4), -#ifdef CONFIG_PV32 - [SH_type_l2h_64_shadow] =3D SHADOW_INTERNAL_NAME(sh_remove_l1_shad= ow, 4), -#endif - [SH_type_l3_64_shadow] =3D SHADOW_INTERNAL_NAME(sh_remove_l2_shado= w, 4), - [SH_type_l4_64_shadow] =3D SHADOW_INTERNAL_NAME(sh_remove_l3_shado= w, 4), - }; - /* Another lookup table, for choosing which mask to use */ static const unsigned int masks[SH_type_unused] =3D { #ifdef CONFIG_HVM @@ -1689,6 +1725,8 @@ void sh_remove_shadows(struct domain *d, /* Search for this shadow in all appropriate shadows */ perfc_incr(shadow_unshadow); =20 +#define callbacks remove_callbacks + /* * Lower-level shadows need to be excised from upper-level shadows. Th= is * call to hash_foreach() looks dangerous but is in fact OK: each call @@ -1736,6 +1774,7 @@ void sh_remove_shadows(struct domain *d, DO_UNSHADOW(SH_type_l1_64_shadow); =20 #undef DO_UNSHADOW +#undef callbacks =20 /* If that didn't catch the shadows, something is wrong */ if ( !fast && all && (pg->count_info & PGC_shadowed_pt) ) --- a/xen/arch/x86/mm/shadow/multi.c +++ b/xen/arch/x86/mm/shadow/multi.c @@ -3644,10 +3644,12 @@ int cf_check sh_remove_l1_shadow(struct =20 FOREACH_PRESENT_L2E(sl2mfn, sl2e, NULL, done, d, { - if ( mfn_eq(shadow_l2e_get_mfn(*sl2e), sl1mfn) ) + mfn_t mfn =3D shadow_l2e_get_mfn(*sl2e); + + if ( !mfn_x(sl1mfn) || mfn_eq(mfn, sl1mfn) ) { shadow_set_l2e(d, sl2e, shadow_l2e_empty(), sl2mfn); - if ( mfn_to_page(sl1mfn)->u.sh.type =3D=3D 0 ) + if ( !mfn_to_page(mfn)->u.sh.type ) /* This breaks us cleanly out of the FOREACH macro */ done =3D 1; } @@ -3664,10 +3666,12 @@ int cf_check sh_remove_l2_shadow(struct =20 FOREACH_PRESENT_L3E(sl3mfn, sl3e, NULL, done, { - if ( mfn_eq(shadow_l3e_get_mfn(*sl3e), sl2mfn) ) + mfn_t mfn =3D shadow_l3e_get_mfn(*sl3e); + + if ( !mfn_x(sl2mfn) || mfn_eq(mfn, sl2mfn) ) { shadow_set_l3e(d, sl3e, shadow_l3e_empty(), sl3mfn); - if ( mfn_to_page(sl2mfn)->u.sh.type =3D=3D 0 ) + if ( !mfn_to_page(mfn)->u.sh.type ) /* This breaks us cleanly out of the FOREACH macro */ done =3D 1; } @@ -3683,10 +3687,12 @@ int cf_check sh_remove_l3_shadow(struct =20 FOREACH_PRESENT_L4E(sl4mfn, sl4e, NULL, done, d, { - if ( mfn_eq(shadow_l4e_get_mfn(*sl4e), sl3mfn) ) + mfn_t mfn =3D shadow_l4e_get_mfn(*sl4e); + + if ( !mfn_x(sl3mfn) || mfn_eq(mfn, sl3mfn) ) { shadow_set_l4e(d, sl4e, shadow_l4e_empty(), sl4mfn); - if ( mfn_to_page(sl3mfn)->u.sh.type =3D=3D 0 ) + if ( !mfn_to_page(mfn)->u.sh.type ) /* This breaks us cleanly out of the FOREACH macro */ done =3D 1; } --- a/xen/arch/x86/mm/shadow/private.h +++ b/xen/arch/x86/mm/shadow/private.h @@ -282,6 +282,9 @@ static inline void sh_terminate_list(str =20 #define SHF_L1_ANY (SHF_L1_32|SHF_L1_PAE|SHF_L1_64) #define SHF_FL1_ANY (SHF_FL1_32|SHF_FL1_PAE|SHF_FL1_64) +#define SHF_L2_ANY (SHF_L2_32|SHF_L2_PAE|SHF_L2H_64|SHF_L2_64) +#define SHF_L3_ANY SHF_L3_64 +#define SHF_L4_ANY SHF_L4_64 =20 #if (SHADOW_OPTIMIZATIONS & SHOPT_OUT_OF_SYNC) /* Marks a guest L1 page table which is shadowed but not write-protected. From nobody Wed Aug 26 01:48:52 2026 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=quarantine dis=none) header.from=suse.com ARC-Seal: i=1; a=rsa-sha256; t=1785248546; cv=none; d=zohomail.com; s=zohoarc; b=kZlD/zD69bgB0e+0wJ2PRNnl+xBeXoPEz5AsZtueFJ5DxG18Kz1yg2j3pWVKqPg2EvyNi+k3pvHiu3KFB+cU5nOvciL+mLD+LyjzMVUpHI+FQ4Osfh8oCWV8u3jNr+zPbhK44EgJS/FVHLl7F3TIWSLtyScoVSUItQdmRDvYqeg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785248546; 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=YAcoPIBVIk35F4UuhNNjahrwo2SklVXZ2m2wuexNepE=; b=hrGGxtAVWR/vcUKItHiSUeLGFzgoAcGgbp5rg4kn1GvEA51hKBZdXQVmW7hasCnS3tSBNoPXwqz6wqS7BoKFuEhewfJXCx95EcKGQezwLuTzdogmgxRpD+rYRCiAfdVrWZudIqVZ7ACijZe4ljXfZX8JB1nk/8KrM1viz/djEog= 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=quarantine dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1785248546597290.58057033417435; Tue, 28 Jul 2026 07:22:26 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1374381.1621539 (Exim 4.92) (envelope-from ) id 1woihD-0002xw-DO; Tue, 28 Jul 2026 14:22:15 +0000 Received: by outflank-mailman (output) from mailman id 1374381.1621539; Tue, 28 Jul 2026 14:22:15 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1woihD-0002xn-Ad; Tue, 28 Jul 2026 14:22:15 +0000 Received: by outflank-mailman (input) for mailman id 1374381; Tue, 28 Jul 2026 14:22:14 +0000 Received: from mx.expurgate.net ([194.145.224.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1woihC-0002xG-Fr for xen-devel@lists.xenproject.org; Tue, 28 Jul 2026 14:22:14 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1woihB-00HOAI-T1 for xen-devel@lists.xenproject.org; Tue, 28 Jul 2026 16:22:13 +0200 Received: from [10.42.69.11] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a68bafb-5cb7-0a2a0a5109dd-0a2a450bc7ee-44 for ; Tue, 28 Jul 2026 16:22:13 +0200 Received: from [209.85.221.46] (helo=mail-wr1-f46.google.com) by tlsNG-42698a.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a68bb15-b7e8-0a2a450b0019-d155dd2eb983-3 for ; Tue, 28 Jul 2026 16:22:13 +0200 Received: by mail-wr1-f46.google.com with SMTP id ffacd0b85a97d-47f84023916so3909473f8f.3 for ; Tue, 28 Jul 2026 07:22:13 -0700 (PDT) Received: from [10.156.60.236] (ip-037-024-206-209.um08.pools.vodafone-ip.de. [37.24.206.209]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-47f85c6f076sm59359286f8f.34.2026.07.28.07.22.12 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 28 Jul 2026 07:22:12 -0700 (PDT) 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" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=google header.d=suse.com header.i="@suse.com" header.h="Content-Transfer-Encoding:Content-Type:In-Reply-To:Autocrypt:Content-Language:References:Cc:To:From:Subject:User-Agent:MIME-Version:Date:Message-ID" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=google; t=1785248533; x=1785853333; darn=lists.xenproject.org; h=content-transfer-encoding:content-type:in-reply-to:autocrypt :content-language:references:cc:to:from:subject:user-agent :mime-version:date:message-id:from:to:cc:subject:date:message-id :reply-to:content-type; bh=YAcoPIBVIk35F4UuhNNjahrwo2SklVXZ2m2wuexNepE=; b=NQT3b/l1U/0AHnFoVyVGdUrKKFGRn8j6g5egzmJbO4CCblTXk6M4llqgKZrtjbPtIg uyRnzuNLtjmp7VQYlfi0C0a8w8UQtrAhVlefLM3UizzB8Ue3lGMFifoLK4fhkCl1czDI 1JJHcyVbuwSzwsoPzkCAehhBKDkK+2tPHd74cjZOKGNF5kMhd3p+nAtS+u8et5A9om/x 0lGCXfP5E1LJyfHZZi5TCpCBS4/h62be4ICpHwxi5sZvIXDk76x+esTd8WEPfA3BlXK5 7crs2NTr2ZBtZZwFeJ/rhPYRB0e/5L4E9T9LOCVTRz7Wc2Dxl8BU35IrghmONgCQr1r5 OHjg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785248533; x=1785853333; h=content-transfer-encoding:content-type:in-reply-to:autocrypt :content-language:references:cc:to:from:subject:user-agent :mime-version:date:message-id:x-gm-gg:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to:content-type; bh=YAcoPIBVIk35F4UuhNNjahrwo2SklVXZ2m2wuexNepE=; b=NO8wQ4YtuZT7DSe/R+npHfP87Q8zGu/gculo4nluzaNUuN0vLLW7QADQ/tAL1L95SD cfwkHbzuC81j3WVSZG9IC7CK9j+xLdK3p0+4MTqnHnbXRTacuBt54Wk+w0xrhIT0V8jD 7xh57B9PEw/L1wPybsKFw/6nSgNqbYpm2aUWTJpHEOmLFjO6HOaPj/TGUelp1ILi6Sp+ 5JdH1L3cy2EFOd2hgzswZGHNiaGNQWINATqnBM+3EPIBNR9P910lPciQMkIiR5ut1T7Q BsAv6x0aiDCGpfTwRLG0k4crfCD2BjOg9dJsiw1ZA7W+miyKZVWCea0amg+KbV/v89kO XN8A== X-Gm-Message-State: AOJu0YwTxgKYLiWaOcCk7fD2JiCf9TvGE6GZMauRthQWQ4kY3kJARUpW gtZH1+9cxRl+4Qi4Ze7IK0s88mf7oAZec+axdpIaX4GIoeceJ2QKPAkm5XHxtv31zySA8O+ETrC ifwHGOQ== X-Gm-Gg: AR+sD12nmcPFH2Nwq84+IJ3jR+z0ggNs8K1Bw6Tpl1wHzUYZxdG+06hrGRaHIzSdVUg Hb8UQ0KmA+SNAdxUFEpaDPYz39S9VyGYN9oodKAf88kMc0fS6KrC+H6HDugs3Z/KNfleWxFzSck q0U29Sgpt2GgUvOIG4JQNc7t8dVZzt2GWlRUse3Oqp/sFO7x3QXoqyVFLfAMrnQmQQpOo6qxGhL XzQvsQ0nSkCO/gi2uNq528SKkzkgddLInwYu83ugb4GqT9uEIOerO+AfjPIuBUkgxSLkFdT95+d /GComwCnD9ue1mzsWlOyXi3/efwTmfyQjpQZgvtoUPLazpLUzMgGeBZYvzXHpqcX77QDpQmzERc SfknWokGuTKerg43ST/3gUJzRGUqt85H9PchsKu6+MCak8ypmA49K4gvPdTafOnXeALBVkmS5wX Q/LxdbB+UJsP3Qq7sVg5ASeudtGZepr5xs3ubQHyrxSx0yqkLtmaqLTQgHqRnqDUtbkjFKf+X+g CHp X-Received: by 2002:a05:6000:22c3:b0:47f:9567:e63b with SMTP id ffacd0b85a97d-47fb1f26115mr3657417f8f.55.1785248533183; Tue, 28 Jul 2026 07:22:13 -0700 (PDT) Message-ID: <274756a3-83da-4594-8909-25a3a9eb94d2@suse.com> Date: Tue, 28 Jul 2026 16:22:11 +0200 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: [PATCH v15 05/10] x86/shadow: make clean-dirty-bitmap post-processing preemptable From: Jan Beulich To: "xen-devel@lists.xenproject.org" Cc: Andrew Cooper , Tim Deegan References: <68c16600-a4bf-4060-a1fc-56c4ae655b03@suse.com> Content-Language: en-US Autocrypt: addr=jbeulich@suse.com; keydata= xsDiBFk3nEQRBADAEaSw6zC/EJkiwGPXbWtPxl2xCdSoeepS07jW8UgcHNurfHvUzogEq5xk hu507c3BarVjyWCJOylMNR98Yd8VqD9UfmX0Hb8/BrA+Hl6/DB/eqGptrf4BSRwcZQM32aZK 7Pj2XbGWIUrZrd70x1eAP9QE3P79Y2oLrsCgbZJfEwCgvz9JjGmQqQkRiTVzlZVCJYcyGGsD /0tbFCzD2h20ahe8rC1gbb3K3qk+LpBtvjBu1RY9drYk0NymiGbJWZgab6t1jM7sk2vuf0Py O9Hf9XBmK0uE9IgMaiCpc32XV9oASz6UJebwkX+zF2jG5I1BfnO9g7KlotcA/v5ClMjgo6Gl MDY4HxoSRu3i1cqqSDtVlt+AOVBJBACrZcnHAUSuCXBPy0jOlBhxPqRWv6ND4c9PH1xjQ3NP nxJuMBS8rnNg22uyfAgmBKNLpLgAGVRMZGaGoJObGf72s6TeIqKJo/LtggAS9qAUiuKVnygo 3wjfkS9A3DRO+SpU7JqWdsveeIQyeyEJ/8PTowmSQLakF+3fote9ybzd880fSmFuIEJldWxp Y2ggPGpiZXVsaWNoQHN1c2UuY29tPsJgBBMRAgAgBQJZN5xEAhsDBgsJCAcDAgQVAggDBBYC AwECHgECF4AACgkQoDSui/t3IH4J+wCfQ5jHdEjCRHj23O/5ttg9r9OIruwAn3103WUITZee e7Sbg12UgcQ5lv7SzsFNBFk3nEQQCACCuTjCjFOUdi5Nm244F+78kLghRcin/awv+IrTcIWF hUpSs1Y91iQQ7KItirz5uwCPlwejSJDQJLIS+QtJHaXDXeV6NI0Uef1hP20+y8qydDiVkv6l IreXjTb7DvksRgJNvCkWtYnlS3mYvQ9NzS9PhyALWbXnH6sIJd2O9lKS1Mrfq+y0IXCP10eS FFGg+Av3IQeFatkJAyju0PPthyTqxSI4lZYuJVPknzgaeuJv/2NccrPvmeDg6Coe7ZIeQ8Yj t0ARxu2xytAkkLCel1Lz1WLmwLstV30g80nkgZf/wr+/BXJW/oIvRlonUkxv+IbBM3dX2OV8 AmRv1ySWPTP7AAMFB/9PQK/VtlNUJvg8GXj9ootzrteGfVZVVT4XBJkfwBcpC/XcPzldjv+3 HYudvpdNK3lLujXeA5fLOH+Z/G9WBc5pFVSMocI71I8bT8lIAzreg0WvkWg5V2WZsUMlnDL9 mpwIGFhlbM3gfDMs7MPMu8YQRFVdUvtSpaAs8OFfGQ0ia3LGZcjA6Ik2+xcqscEJzNH+qh8V m5jjp28yZgaqTaRbg3M/+MTbMpicpZuqF4rnB0AQD12/3BNWDR6bmh+EkYSMcEIpQmBM51qM EKYTQGybRCjpnKHGOxG0rfFY1085mBDZCH5Kx0cl0HVJuQKC+dV2ZY5AqjcKwAxpE75MLFkr wkkEGBECAAkFAlk3nEQCGwwACgkQoDSui/t3IH7nnwCfcJWUDUFKdCsBH/E5d+0ZnMQi+G0A nAuWpQkjM1ASeQwSHEeAWPgskBQL In-Reply-To: <68c16600-a4bf-4060-a1fc-56c4ae655b03@suse.com> Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-42698a/1785248533-A86CA9EA-898524F5/0/0 X-purgate-type: clean X-purgate-size: 6534 X-ZohoMail-DKIM: pass (identity @suse.com) X-ZM-MESSAGEID: 1785248548728158500 Content-Type: text/plain; charset="utf-8" What this currently amounts to is blowing the domain's tables. To make that call preemptable and to record state in a race-free manner, it needs to be moved inside the paging-locked region. Since the corresponding HAP function wants to acquire the P2M lock, the hook invocation itself cannot be moved. Call the shadow function directly, and prevent the hook from being invoked in that case. To prevent "extra" accounting from being done more than once in paging_log_dirty_op(), the mapping of the top level table also becomes conditional (upon the subsequent loop doing nothing anyway). Further note that this now also avoids sh{,adow}_clean_dirty_bitmap() needlessly being called when no paging mode was enabled at all for the domain. (The function continues to be called even when log-dirty mode isn't enabled.) Signed-off-by: Jan Beulich --- The hook functions were/are slightly mis-named, as they don't clean anything. However, to keep names similar (and hence possible to grep for) the new directly called function is still named in the same manner. Of course we could purge the hook altogether, calling the HAP function directly as well. If so, question would be whether to do so right here or in a public follow-up (perhaps the latter). In the course of doing this work I've noticed that libxenguest uses XEN_DOMCTL_SHADOW_OP_CLEAN even on the last iteration. Wouldn't it suffice to invoke the non-cleaning (peek) operation there instead, reducing the overhead of shadow's post-processing? --- v15: Fix !SHADOW_PAGING build. v14: New. --- a/xen/arch/x86/include/asm/domain.h +++ b/xen/arch/x86/include/asm/domain.h @@ -234,7 +234,7 @@ struct paging_domain { union { struct { unsigned long done:PADDR_BITS - PAGE_SHIFT; - unsigned long i4:PAGETABLE_ORDER; + unsigned long i4:PAGETABLE_ORDER + 1; unsigned long i3:PAGETABLE_ORDER; } log_dirty; }; --- a/xen/arch/x86/include/asm/shadow.h +++ b/xen/arch/x86/include/asm/shadow.h @@ -56,6 +56,9 @@ int shadow_domain_init(struct domain *d) * paging_vcpu_init() in paging.c */ void shadow_vcpu_init(struct vcpu *v); =20 +/* Post-processing necessary after the log-dirty bitmap was cleaned. */ +bool shadow_clean_dirty_bitmap(struct domain *d); + #ifdef CONFIG_SHADOW_PAGING =20 /* Enable an arbitrary shadow mode. Call once at domain creation. */ --- a/xen/arch/x86/mm/paging.c +++ b/xen/arch/x86/mm/paging.c @@ -473,8 +473,9 @@ static int paging_log_dirty_op(struct do goto out; } =20 - l4 =3D paging_map_log_dirty_bitmap(d); i4 =3D d->arch.paging.preempt.log_dirty.i4; + if ( i4 < LOGDIRTY_NODE_ENTRIES ) + l4 =3D paging_map_log_dirty_bitmap(d); i3 =3D d->arch.paging.preempt.log_dirty.i3; pages =3D d->arch.paging.preempt.log_dirty.done; =20 @@ -542,6 +543,19 @@ static int paging_log_dirty_op(struct do if ( l4 ) unmap_domain_page(l4); =20 + /* + * In the shadow case post-processing may take long and hence needs to= be + * preemptable. Since continuation state is protected by the paging lo= ck, + * we need to call its function (and record state) before dropping that + * lock. The hook invocation further down therefore will be skipped. + */ + if ( !rv && clean && paging_mode_shadow(d) && + !shadow_clean_dirty_bitmap(d) ) + { + d->arch.paging.preempt.log_dirty.i4 =3D LOGDIRTY_NODE_ENTRIES; + rv =3D -ERESTART; + } + if ( !rv ) { d->arch.paging.preempt.dom =3D NULL; @@ -569,10 +583,12 @@ static int paging_log_dirty_op(struct do =20 if ( pages < sc->pages ) sc->pages =3D pages; - if ( clean ) + if ( clean && paging_mode_hap(d) ) { - /* We need to further call clean_dirty_bitmap() functions of speci= fic - * paging modes (shadow or hap). Safe because the domain is pause= d. */ + /* + * We need to further call HAP's clean_dirty_bitmap() function (sh= adow + * was dealt with above). Safe because the domain is paused. + */ d->arch.paging.log_dirty.ops->clean(d); } domain_unpause(d); --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -71,7 +71,6 @@ DEFINE_PER_CPU(uint32_t,trace_shadow_pat =20 static int cf_check sh_enable_log_dirty(struct domain *d); static int cf_check sh_disable_log_dirty(struct domain *d); -static void cf_check sh_clean_dirty_bitmap(struct domain *d); =20 static void cf_check shadow_update_paging_modes(struct vcpu *v); =20 @@ -82,7 +81,7 @@ int shadow_domain_init(struct domain *d) static const struct log_dirty_ops sh_ops =3D { .enable =3D sh_enable_log_dirty, .disable =3D sh_disable_log_dirty, - .clean =3D sh_clean_dirty_bitmap, + .clean =3D ZERO_BLOCK_PTR, }; =20 INIT_PAGE_LIST_HEAD(&d->arch.paging.shadow.pinned_shadows); @@ -2606,14 +2605,18 @@ static int cf_check sh_disable_log_dirty /* This function is called when we CLEAN log dirty bitmap. See * paging_log_dirty_op() for details. */ -static void cf_check sh_clean_dirty_bitmap(struct domain *d) +bool shadow_clean_dirty_bitmap(struct domain *d) { - paging_lock(d); + bool preempted =3D false; + + ASSERT(paging_locked_by_me(d)); + /* Need to revoke write access to the domain's pages again. * In future, we'll have a less heavy-handed approach to this, * but for now, we just unshadow everything except Xen. */ - shadow_blow_tables(d, NULL); - paging_unlock(d); + shadow_blow_tables(d, &preempted); + + return !preempted; } =20 /*************************************************************************= */ --- a/xen/arch/x86/mm/shadow/none.c +++ b/xen/arch/x86/mm/shadow/none.c @@ -7,11 +7,6 @@ static int cf_check _toggle_log_dirty(st return -EOPNOTSUPP; } =20 -static void cf_check _clean_dirty_bitmap(struct domain *d) -{ - ASSERT(is_pv_domain(d)); -} - static void cf_check _update_paging_modes(struct vcpu *v) { ASSERT_UNREACHABLE(); @@ -23,7 +18,7 @@ int shadow_domain_init(struct domain *d) static const struct log_dirty_ops sh_none_ops =3D { .enable =3D _toggle_log_dirty, .disable =3D _toggle_log_dirty, - .clean =3D _clean_dirty_bitmap, + .clean =3D ZERO_BLOCK_PTR, }; =20 paging_log_dirty_init(d, &sh_none_ops); From nobody Wed Aug 26 01:48:52 2026 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=quarantine dis=none) header.from=suse.com ARC-Seal: i=1; a=rsa-sha256; t=1785248575; cv=none; d=zohomail.com; s=zohoarc; b=hhInwM8l9vxoYPJwNHFhC3Xar+NQq3HsUC885MP6dPll5831XjQhB1iiA285r+pfWT3q1GVQVQm4AX7UtGOuNs9uPno0WMx3vOBqfE3CsVDo4EjfyvyUd/Z+Tf7SqMtImnFCidKkEweL4HLjnIJKGoDEHzvWee5GRbk1ALLGF3E= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785248575; 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=xzunNfHOxzhHTSPk1dD1REpFH01TRuP3mjZJ3vTTN8k=; b=DAWkSQZztA/GGDWRHhsziRZR9dyLu2Xb8c6bTGEyNeevGtIoiMGyNPnRQQP/pYLk8sT8uxt2fC5GT8UB+4Id5DRzS43nGp2MtBMY3JDwAW/L0fCaI9eeBpsLdxkS0n14A8/MHHxKQ3VuBGAUdXT2NSk+QRNyt9sroKLztTI+lLo= 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=quarantine dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1785248575097737.4911626908906; Tue, 28 Jul 2026 07:22:55 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1374391.1621549 (Exim 4.92) (envelope-from ) id 1woihb-0003VQ-Lm; Tue, 28 Jul 2026 14:22:39 +0000 Received: by outflank-mailman (output) from mailman id 1374391.1621549; Tue, 28 Jul 2026 14:22:39 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1woihb-0003VH-Iq; Tue, 28 Jul 2026 14:22:39 +0000 Received: by outflank-mailman (input) for mailman id 1374391; Tue, 28 Jul 2026 14:22:37 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1woihZ-0003Sw-OR for xen-devel@lists.xenproject.org; Tue, 28 Jul 2026 14:22:37 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1woihZ-004xTM-5A for xen-devel@lists.xenproject.org; Tue, 28 Jul 2026 16:22:37 +0200 Received: from [10.42.69.8] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a68bb1e-2eae-0a2a0a5409dd-0a2a450880f2-28 for ; Tue, 28 Jul 2026 16:22:37 +0200 Received: from [209.85.128.50] (helo=mail-wm1-f50.google.com) by tlsNG-c1860d.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a68bb2c-f659-0a2a45080019-d1558032c93b-3 for ; Tue, 28 Jul 2026 16:22:37 +0200 Received: by mail-wm1-f50.google.com with SMTP id 5b1f17b1804b1-493b966dd74so24570335e9.3 for ; Tue, 28 Jul 2026 07:22:37 -0700 (PDT) Received: from [10.156.60.236] (ip-037-024-206-209.um08.pools.vodafone-ip.de. [37.24.206.209]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-496c44a873csm85807545e9.2.2026.07.28.07.22.34 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 28 Jul 2026 07:22:35 -0700 (PDT) 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" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=google header.d=suse.com header.i="@suse.com" header.h="Content-Transfer-Encoding:Content-Type:In-Reply-To:Autocrypt:Content-Language:References:Cc:To:From:Subject:User-Agent:MIME-Version:Date:Message-ID" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=google; t=1785248556; x=1785853356; darn=lists.xenproject.org; h=content-transfer-encoding:content-type:in-reply-to:autocrypt :content-language:references:cc:to:from:subject:user-agent :mime-version:date:message-id:from:to:cc:subject:date:message-id :reply-to:content-type; bh=xzunNfHOxzhHTSPk1dD1REpFH01TRuP3mjZJ3vTTN8k=; b=eLA93yqF4LR0hFlDou/xeKlw5KABpSb/Mup8kNmCEbASP0MgpD85jUkerJepjllZ1N 8BkpSefeBza2K5D5EXHzGOn5wB2IaFTDpXTAJtV4x4+RzPeQU9glutoMBhRGW+HXv/Jw r3ROGKTa7r9uxm0X0S2QHH+U2Z0/L92UaacpUH8VlQwnHimse7+UK4WvZWedMv82DPPr 7iV16mU2kByI8jWDNECTN3HkjYz5dOD6C2w11LZtu3/lwqIwLvkzx6QdmvrkXur3pBVP 81bYJ37oSfeGzxRqEhn/POE8flwGun60tLRZxsFNDYJmegESb6W2QwzluRBj9OonUnxK QBHw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785248556; x=1785853356; h=content-transfer-encoding:content-type:in-reply-to:autocrypt :content-language:references:cc:to:from:subject:user-agent :mime-version:date:message-id:x-gm-gg:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to:content-type; bh=xzunNfHOxzhHTSPk1dD1REpFH01TRuP3mjZJ3vTTN8k=; b=Xdc5XD+iEa4IxGnFBak/G5RHGo4zyRbeqnbwM06s7kCPCreGc3smuzTZ1ZHJbrkyIn 1ziT4LewEhv+9dWK/a/449Ruf9QKeAM5h0vWIKEUeKDVBxBRGX/z67Jhf3PN/jZ7IRuG eD60z643lP7BfHakREj/U7BNSs4YdKlKIPGnVfymDxYNDtp0ClmDqdbqBV2Fg/6wgw7k fDl79DjSXA/zERbD96kmwaL6YhAP0wIlsOaN/lRtxQ4O7kWdIzxRJXVTBCH+Eov4VRv0 VpQmC04Pg9PZJsiLBjAQlusO6faIKwlO7rP9ApB4CCfFwDeNlwZEQ92SvBc+fv1holMt E9kg== X-Gm-Message-State: AOJu0Yyi4MC4ku0OGvL24BxdoKMHLA5kO1pW3Py/2Ql9T8jIKPe7xJDv FqrjtOXXbyMFdd9WTqNDsiAVotkc2fl0MJLto3bAqyvBazmGWqUbN/gZDu38ThFOXyU+GkXWgr8 bOUAsiA== X-Gm-Gg: AR+sD11Vws+2fpvMZPiGMYeNq42GJFznq/OIurkfQ52XVPv04wyMgFeCzS+gALzFkSh g3RbSVhfjGVnhNXjbbRUdcshb76amS6K41EeMc83W17dfL1FTIpQGpqi9BBqhnpETTatWCZUWPa lMIiIQ0HcVdBcibbcndyFjhrMwwceKJyX5wLwE3XR2w0zeSSFJEzXJ8c2wuvWPPeGYw4gHW4i7b jCOhkC139kEcttF+dne2cm4gVU7Aky9j1T2+2d5eabfCTuuddVsyTjh57DnfVJJakojQ4rOyWKi u31xJfTgatBndY8okzCvQKp3E9r5o+kGLOeC6OJ79HEAuhkcyyBvvxVnDVvvk690j0MsEFFpMii NQAq7TgGxg4ID9MXqJ8sfN8mjvPtaq66J1kNmj254a1NV0RyHChbGVZejYhzAsEFER2BP53ozJw Ybcu/2J7OhGYyDcORSVTGWE51gyTgOjY7Kiw62fW8SHZ0X8PamvTD/cJAHlfz8YtmLqX+mBNGVd ReE5AKCBbYDL24= X-Received: by 2002:a05:600c:c16d:b0:493:c8a6:b517 with SMTP id 5b1f17b1804b1-496c6588c3cmr27756545e9.38.1785248556294; Tue, 28 Jul 2026 07:22:36 -0700 (PDT) Message-ID: Date: Tue, 28 Jul 2026 16:22:34 +0200 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: [PATCH v15 06/10] x86/mm: make more of log-dirty mode enable/disable preemptable From: Jan Beulich To: "xen-devel@lists.xenproject.org" Cc: Andrew Cooper , Tim Deegan References: <68c16600-a4bf-4060-a1fc-56c4ae655b03@suse.com> Content-Language: en-US Autocrypt: addr=jbeulich@suse.com; keydata= xsDiBFk3nEQRBADAEaSw6zC/EJkiwGPXbWtPxl2xCdSoeepS07jW8UgcHNurfHvUzogEq5xk hu507c3BarVjyWCJOylMNR98Yd8VqD9UfmX0Hb8/BrA+Hl6/DB/eqGptrf4BSRwcZQM32aZK 7Pj2XbGWIUrZrd70x1eAP9QE3P79Y2oLrsCgbZJfEwCgvz9JjGmQqQkRiTVzlZVCJYcyGGsD /0tbFCzD2h20ahe8rC1gbb3K3qk+LpBtvjBu1RY9drYk0NymiGbJWZgab6t1jM7sk2vuf0Py O9Hf9XBmK0uE9IgMaiCpc32XV9oASz6UJebwkX+zF2jG5I1BfnO9g7KlotcA/v5ClMjgo6Gl MDY4HxoSRu3i1cqqSDtVlt+AOVBJBACrZcnHAUSuCXBPy0jOlBhxPqRWv6ND4c9PH1xjQ3NP nxJuMBS8rnNg22uyfAgmBKNLpLgAGVRMZGaGoJObGf72s6TeIqKJo/LtggAS9qAUiuKVnygo 3wjfkS9A3DRO+SpU7JqWdsveeIQyeyEJ/8PTowmSQLakF+3fote9ybzd880fSmFuIEJldWxp Y2ggPGpiZXVsaWNoQHN1c2UuY29tPsJgBBMRAgAgBQJZN5xEAhsDBgsJCAcDAgQVAggDBBYC AwECHgECF4AACgkQoDSui/t3IH4J+wCfQ5jHdEjCRHj23O/5ttg9r9OIruwAn3103WUITZee e7Sbg12UgcQ5lv7SzsFNBFk3nEQQCACCuTjCjFOUdi5Nm244F+78kLghRcin/awv+IrTcIWF hUpSs1Y91iQQ7KItirz5uwCPlwejSJDQJLIS+QtJHaXDXeV6NI0Uef1hP20+y8qydDiVkv6l IreXjTb7DvksRgJNvCkWtYnlS3mYvQ9NzS9PhyALWbXnH6sIJd2O9lKS1Mrfq+y0IXCP10eS FFGg+Av3IQeFatkJAyju0PPthyTqxSI4lZYuJVPknzgaeuJv/2NccrPvmeDg6Coe7ZIeQ8Yj t0ARxu2xytAkkLCel1Lz1WLmwLstV30g80nkgZf/wr+/BXJW/oIvRlonUkxv+IbBM3dX2OV8 AmRv1ySWPTP7AAMFB/9PQK/VtlNUJvg8GXj9ootzrteGfVZVVT4XBJkfwBcpC/XcPzldjv+3 HYudvpdNK3lLujXeA5fLOH+Z/G9WBc5pFVSMocI71I8bT8lIAzreg0WvkWg5V2WZsUMlnDL9 mpwIGFhlbM3gfDMs7MPMu8YQRFVdUvtSpaAs8OFfGQ0ia3LGZcjA6Ik2+xcqscEJzNH+qh8V m5jjp28yZgaqTaRbg3M/+MTbMpicpZuqF4rnB0AQD12/3BNWDR6bmh+EkYSMcEIpQmBM51qM EKYTQGybRCjpnKHGOxG0rfFY1085mBDZCH5Kx0cl0HVJuQKC+dV2ZY5AqjcKwAxpE75MLFkr wkkEGBECAAkFAlk3nEQCGwwACgkQoDSui/t3IH7nnwCfcJWUDUFKdCsBH/E5d+0ZnMQi+G0A nAuWpQkjM1ASeQwSHEeAWPgskBQL In-Reply-To: <68c16600-a4bf-4060-a1fc-56c4ae655b03@suse.com> Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-c1860d/1785248557-CED4087B-82A37201/0/0 X-purgate-type: clean X-purgate-size: 10439 X-ZohoMail-DKIM: pass (identity @suse.com) X-ZM-MESSAGEID: 1785248576898158500 Content-Type: text/plain; charset="utf-8" So far only part of disable was preemptable. Shadow code, however, will need to purge all earlier shadows, which may take quite a bit of time. In the general (paging) layer arrange for the hook functions to possibly indicate the need for resuming. In shadow code leverage "enable" already calling shadow_blow_tables(), simply making that call preemptable, while adding a call to that function for "disable". In order for resume state to be properly guarded, the paging lock now needs acquiring in paging_log_dirty_{en,dis}able(). HAP's need to acquire the P2M lock makes it necessary to allow the hook functions to drop the paging lock. Note that when requesting resuming, the hook functions must not have changed the paging (shadow) mode yet; the actual mode change part is expected to be performed quickly enough to not require preemption. This is why "blow" (done ahead of mode switching) is preferred over "detach-old" (occurring with mode already updated). While this may mean more purging being done now for "disable", starting from a clean state afterwards may be better overall anyway. Note further that HAP code is, except for the locking adjustments, (intended to be) largely unaffected, for not having a need for preemption checking. Signed-off-by: Jan Beulich --- Locking isn't really nice here, but I see no better way given HAP's need to acquire the P2M lock in its hook functions. Things may end up a little better if doing away with the hooks and handling HAP and shadow (in part) separately in paging.c, and then building upon HAP not needing any preemption checking. Yet whether purging the hooks right here is okay is unclear (see also "x86/shadow: make clean-dirty-bitmap post-processing preemptable", where the question also arises). See also the comments in "x86/shadow: 1-bit-disable doesn't need to detach old tables". Specifically avoiding shadow_blow_tables() here would mean pinned shadows wouldn't be needlessly unpinned. --- v15: Add missing domain_unpause() to paging_log_dirty_enable()'s HAP path. Re-base. v14: (Re)check and update preemption state under paging lock. Adjust locking accordingly. Re-base. v13: New. --- a/xen/arch/x86/include/asm/domain.h +++ b/xen/arch/x86/include/asm/domain.h @@ -199,6 +199,11 @@ struct log_dirty_domain { =20 /* functions which are paging mode specific */ const struct log_dirty_ops { + /* + * enable() and disable() will be called with the paging lock held. + * They may drop the lock (but not drop and re-acquire it), but th= en + * need to indicate so by returning a positive value. + */ int (*enable )(struct domain *d); int (*disable )(struct domain *d); void (*clean )(struct domain *d); --- a/xen/arch/x86/mm/hap/hap.c +++ b/xen/arch/x86/mm/hap/hap.c @@ -184,7 +184,7 @@ static int cf_check hap_enable_log_dirty return -EBUSY; =20 /* turn on PG_log_dirty bit in paging mode */ - paging_lock(d); + ASSERT(paging_locked_by_me(d)); d->arch.paging.mode |=3D PG_log_dirty; paging_unlock(d); =20 @@ -198,12 +198,12 @@ static int cf_check hap_enable_log_dirty p2m_change_entry_type_global(d, p2m_ram_rw, p2m_ram_logdirty); guest_flush_tlb_mask(d, d->dirty_cpumask); =20 - return 0; + return 1; } =20 static int cf_check hap_disable_log_dirty(struct domain *d) { - paging_lock(d); + ASSERT(paging_locked_by_me(d)); d->arch.paging.mode &=3D ~PG_log_dirty; paging_unlock(d); =20 @@ -215,7 +215,7 @@ static int cf_check hap_disable_log_dirt * normal mode, or via hardware-assisted log-dirty. */ p2m_change_entry_type_global(d, p2m_ram_logdirty, p2m_ram_rw); - return 0; + return 1; } =20 static void cf_check hap_clean_dirty_bitmap(struct domain *d) --- a/xen/arch/x86/mm/paging.c +++ b/xen/arch/x86/mm/paging.c @@ -104,13 +104,10 @@ static int paging_free_log_dirty_bitmap( mfn_t *l4, *l3, *l2; int i4, i3, i2; =20 - paging_lock(d); + ASSERT(paging_locked_by_me(d)); =20 if ( mfn_eq(d->arch.paging.log_dirty.top, INVALID_MFN) ) - { - paging_unlock(d); return 0; - } =20 if ( !d->arch.paging.preempt.dom ) { @@ -121,10 +118,7 @@ static int paging_free_log_dirty_bitmap( } else if ( d->arch.paging.preempt.dom !=3D current->domain || d->arch.paging.preempt.op !=3D XEN_DOMCTL_SHADOW_OP_OFF ) - { - paging_unlock(d); return -EBUSY; - } =20 l4 =3D map_domain_page(d->arch.paging.log_dirty.top); i4 =3D d->arch.paging.preempt.log_dirty.i4; @@ -196,12 +190,11 @@ static int paging_free_log_dirty_bitmap( d->arch.paging.preempt.op =3D XEN_DOMCTL_SHADOW_OP_OFF; } =20 - paging_unlock(d); - return rc; } =20 -static int paging_log_dirty_enable(struct domain *d) +static int paging_log_dirty_enable(struct domain *d, unsigned int op, + bool resuming) { int ret; =20 @@ -217,9 +210,42 @@ static int paging_log_dirty_enable(struc if ( paging_mode_log_dirty(d) ) return -EINVAL; =20 - domain_pause(d); + if ( !resuming ) + domain_pause(d); + + paging_lock(d); + + if ( d->arch.paging.preempt.dom && + (d->arch.paging.preempt.dom !=3D current->domain || + d->arch.paging.preempt.op !=3D op) ) + { + paging_unlock(d); + if ( !resuming ) + domain_unpause(d); + return -EBUSY; + } + ret =3D d->arch.paging.log_dirty.ops->enable(d); - domain_unpause(d); + + if ( ret > 0 ) + { + /* Paging lock dropped by hook. */ + domain_unpause(d); + ret =3D 0; + } + else if ( ret !=3D -ERESTART ) + { + d->arch.paging.preempt.dom =3D NULL; + paging_unlock(d); + domain_unpause(d); + } + else + { + ASSERT(!paging_mode_log_dirty(d)); + d->arch.paging.preempt.dom =3D current->domain; + d->arch.paging.preempt.op =3D op; + paging_unlock(d); + } =20 return ret; } @@ -229,21 +255,49 @@ static int paging_log_dirty_disable(stru int ret =3D 1; =20 if ( !resuming ) - { domain_pause(d); - /* Safe because the domain is paused. */ - if ( paging_mode_log_dirty(d) ) + + paging_lock(d); + + if ( d->arch.paging.preempt.dom && + (d->arch.paging.preempt.dom !=3D current->domain || + d->arch.paging.preempt.op !=3D XEN_DOMCTL_SHADOW_OP_OFF) ) + { + paging_unlock(d); + if ( !resuming ) + domain_unpause(d); + return -EBUSY; + } + + /* Safe because the domain is paused. */ + if ( paging_mode_log_dirty(d) ) + { + ret =3D d->arch.paging.log_dirty.ops->disable(d); + if ( ret > 0 ) /* Paging lock dropped by hook? */ + { + paging_lock(d); + ret =3D 0; + } + else if ( ret !=3D -ERESTART ) + d->arch.paging.preempt.dom =3D NULL; + else { - ret =3D d->arch.paging.log_dirty.ops->disable(d); - ASSERT(ret <=3D 0); + ASSERT(paging_mode_log_dirty(d)); + d->arch.paging.preempt.dom =3D current->domain; + d->arch.paging.preempt.op =3D XEN_DOMCTL_SHADOW_OP_OFF; + paging_unlock(d); + return ret; } + + ASSERT(ret < 0 || !paging_mode_log_dirty(d)); } =20 ret =3D paging_free_log_dirty_bitmap(d, ret); - if ( ret =3D=3D -ERESTART ) - return ret; =20 - domain_unpause(d); + paging_unlock(d); + + if ( ret !=3D -ERESTART ) + domain_unpause(d); =20 return ret; } @@ -720,7 +774,7 @@ int paging_domctl(struct domain *d, stru break; fallthrough; case XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY: - return paging_log_dirty_enable(d); + return paging_log_dirty_enable(d, sc->op, resuming); =20 case XEN_DOMCTL_SHADOW_OP_OFF: if ( (rc =3D paging_log_dirty_disable(d, resuming)) !=3D 0 ) @@ -812,7 +866,9 @@ int paging_teardown(struct domain *d) =20 #if PG_log_dirty /* clean up log dirty resources. */ + paging_lock(d); rc =3D paging_free_log_dirty_bitmap(d, 0); + paging_unlock(d); if ( rc =3D=3D -ERESTART ) return rc; #endif --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -2567,13 +2567,22 @@ static int cf_check sh_enable_log_dirty( { int ret; =20 - paging_lock(d); + ASSERT(paging_locked_by_me(d)); + if ( shadow_mode_enabled(d) ) { - /* This domain already has some shadows: need to clear them out + bool preempted =3D false; + + /* + * This domain already has some shadows: need to clear them out * of the way to make sure that all references to guest memory are - * properly write-protected */ - shadow_blow_tables(d, NULL); + * properly write-protected. + * + * Furthermore see sh_disable_log_dirty() below. + */ + shadow_blow_tables(d, &preempted); + if ( preempted ) + return -ERESTART; } =20 #if (SHADOW_OPTIMIZATIONS & SHOPT_LINUX_L3_TOPLEVEL) @@ -2585,7 +2594,6 @@ static int cf_check sh_enable_log_dirty( #endif =20 ret =3D shadow_one_bit_enable(d, PG_log_dirty); - paging_unlock(d); =20 return ret; } @@ -2593,13 +2601,18 @@ static int cf_check sh_enable_log_dirty( /* shadow specfic code which is called in paging_log_dirty_disable() */ static int cf_check sh_disable_log_dirty(struct domain *d) { - int ret; + bool preempted =3D false; =20 - paging_lock(d); - ret =3D shadow_one_bit_disable(d, PG_log_dirty); - paging_unlock(d); + ASSERT(paging_locked_by_me(d)); =20 - return ret; + /* + * Limit the amount of work to do from sh_detach_old_tables() (called = from + * shadow_one_bit_disable() via sh_new_mode() -> sh_update_paging_mode= s()), + * such that it doesn't also need to deal with preemption checks. + */ + shadow_blow_tables(d, &preempted); + + return preempted ? -ERESTART : shadow_one_bit_disable(d, PG_log_dirty); } =20 /* This function is called when we CLEAN log dirty bitmap. See From nobody Wed Aug 26 01:48:52 2026 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=quarantine dis=none) header.from=suse.com ARC-Seal: i=1; a=rsa-sha256; t=1785248594; cv=none; d=zohomail.com; s=zohoarc; b=ejes0VpF3Xh2LDta51f2jGzEYz3USXTJcNbK6Gu05FZ9LFNmfLJg2gUkjwp276dOktj4S1IbzO3eLCfKpO1LrX84HpONwojU06G9WqBQSc8AvYPNLefg2bPgvbz6NaxolC1tAbsgHbRWagmmSdZREatczshR8D1kPEgudNFmHzc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785248594; 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=g3jdcGX3ZHkyd51//1sqLgUrNqK78wVltQSxO9SrAuc=; b=OEw9czh1x87AAp24IZN8OyEdFv2aIfsyuW5scihxvbTGeNbdlOI3iOrAFc4R+vbeJsPFjsd+n5n1zHrkEVqOH00IDtrxuYsUeGj9qppXFaQ4Xb3Mw7cbrnygXKZYSLsEk3RZ5BUjkUAPlcYNTdDZkTZfiyc8XGOm2uP+Ns9Ds3U= 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=quarantine dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1785248594669166.40526448495189; Tue, 28 Jul 2026 07:23:14 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1374396.1621558 (Exim 4.92) (envelope-from ) id 1woihx-0003xk-0D; Tue, 28 Jul 2026 14:23:01 +0000 Received: by outflank-mailman (output) from mailman id 1374396.1621558; Tue, 28 Jul 2026 14:23:00 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1woihw-0003xa-TD; Tue, 28 Jul 2026 14:23:00 +0000 Received: by outflank-mailman (input) for mailman id 1374396; Tue, 28 Jul 2026 14:22:59 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1woihv-0003vs-1N for xen-devel@lists.xenproject.org; Tue, 28 Jul 2026 14:22:59 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1woihu-004xX0-E4 for xen-devel@lists.xenproject.org; Tue, 28 Jul 2026 16:22:58 +0200 Received: from [10.42.69.2] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a68bb33-2eae-0a2a0a5409dd-0a2a4502ac72-34 for ; Tue, 28 Jul 2026 16:22:58 +0200 Received: from [209.85.128.54] (helo=mail-wm1-f54.google.com) by tlsNG-720697.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a68bb42-6ca4-0a2a45020019-d1558036c5e5-3 for ; Tue, 28 Jul 2026 16:22:58 +0200 Received: by mail-wm1-f54.google.com with SMTP id 5b1f17b1804b1-4954c0833b4so29224255e9.1 for ; Tue, 28 Jul 2026 07:22:58 -0700 (PDT) Received: from [10.156.60.236] (ip-037-024-206-209.um08.pools.vodafone-ip.de. [37.24.206.209]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-496c45cb67esm86210395e9.8.2026.07.28.07.22.56 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 28 Jul 2026 07:22:57 -0700 (PDT) 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" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=google header.d=suse.com header.i="@suse.com" header.h="Content-Transfer-Encoding:Content-Type:In-Reply-To:Autocrypt:Content-Language:References:Cc:To:From:Subject:User-Agent:MIME-Version:Date:Message-ID" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=google; t=1785248578; x=1785853378; darn=lists.xenproject.org; h=content-transfer-encoding:content-type:in-reply-to:autocrypt :content-language:references:cc:to:from:subject:user-agent :mime-version:date:message-id:from:to:cc:subject:date:message-id :reply-to:content-type; bh=g3jdcGX3ZHkyd51//1sqLgUrNqK78wVltQSxO9SrAuc=; b=Y9RlXmUOcWtX+GwCgMBsFEzimD6JRZTYK2LYylH3qwhfThBD//MjWLF5Ba0hZ3yKfa x6XJ8apVIATXZ6EswDohIYzTXZU/EOg6I2+QNxCvbokA9h9dpmR7vysJ7YpaE2k9FsJb 0hxYc7gIdB5eUYAUNE3pEqVyT4sAFKv/yt4kXZht1QSud1C20LD2T8W6cGRGkyJF70rb macKyD9jlj8V37eyJXwUnoPB4ukmoRvN25yQB+fX3xNn1DUq2/7tTlg+4p+a2d+04LBC +dEwhiN6JgLWCJnLvMLFPrkBVrEkoMVTXPAOYMiNav3ZNqDCc6cyWAnAgCmanVXcwX1p OVVg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785248578; x=1785853378; h=content-transfer-encoding:content-type:in-reply-to:autocrypt :content-language:references:cc:to:from:subject:user-agent :mime-version:date:message-id:x-gm-gg:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to:content-type; bh=g3jdcGX3ZHkyd51//1sqLgUrNqK78wVltQSxO9SrAuc=; b=hjZ2e9pJa35shCImeyh517OQi4OVNWeglr4zBQlxv5o0B4RUvtRWC/ANLKMZPZOrF2 vV28S7wCPKw375NJGTxdP1oVZlZWiu34p5/ckHVEuS/OVOfFrYN2mSBIdh4DnIgQSnIu CxTI5zUmgvF/YXV6TEtutif/FUYhKd9lCvjMVRbb+rk6NOJ1Z9WrBaKEfaZoyo2INZJH hx+ZBjG0cvJ2dwQgBUAGSmoheA9VT6cYF2p1kgKuhIbhy/kkmLkA09r6f02fK8JrgcuK VmU1ZTSCGQFonBN3Z5ad2NpT+WGFGUwgJgwQ1GRkM+NWojNVC8fPJnPy6rZGcq+QFLHr 6fIw== X-Gm-Message-State: AOJu0YwRmH4vOMipMzX7qEjh0vE/4SF6f9nGsKtp7PrcPJzS+dqzpUHD eU0bCtjmw8oTOMW8GZB1lpv0TlT5SbtcEJI13G/dAVavdcQiRn17YPhTVtGE0ddufzt7j9S6aS7 l4nINPQ== X-Gm-Gg: AR+sD13yBajch73kdiVRIQhcaFWCgSUNXLtU6hjeItOaM648ur7iBQ2BKsNvk94tYe6 fuuj3VbtSg/wd3+vhUZOdWZ3m7RvRIDMncSfcnSrwhP7Psu+FWxdHLTqprXE95G718IxfU4T2P5 D1nr/ZqiQjYVZQOLr630pSs4Las0Gw5YmoHsCHWc674r6DaGj2CSIZSHjDpeJ2dXNTsGxGXDZaC kjZ6iYQ9tWXwb2GtqETUYITsmSIbQJTX5vCFQAfR6j1XZ6WM5s3Zbq1cc5xaWlMFY38Xi+fK8ml V/ex10uqyaMwDp2YNABLuWOMfgoyjUI3Y5JB5xFrqRd+KtUM4e0bVMis3dEOx+iIAIqrdoazQk+ ponDgblXH7KeujOy+wRHBqoNkOsLcDncPLPVBiK0V3Ep2SG8fbqtJyW3KbFFv4j0NAVz3qbQmvl 7qrkCoG+ScrYrlXhCWtOVJcE9ndhBhwtCd+8ttjlemS38/98PWH0p8KHieRcdTGJ3bjw== X-Received: by 2002:a05:600c:6095:b0:495:6022:5a14 with SMTP id 5b1f17b1804b1-496c65802a3mr28931925e9.34.1785248577796; Tue, 28 Jul 2026 07:22:57 -0700 (PDT) Message-ID: <548d021a-7299-4ca4-afae-00fce1c1d549@suse.com> Date: Tue, 28 Jul 2026 16:22:56 +0200 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: [PATCH v15 07/10] x86/shadow: fold _shadow_prealloc() with shadow_blow_tables() From: Jan Beulich To: "xen-devel@lists.xenproject.org" Cc: Andrew Cooper , Tim Deegan References: <68c16600-a4bf-4060-a1fc-56c4ae655b03@suse.com> Content-Language: en-US Autocrypt: addr=jbeulich@suse.com; keydata= xsDiBFk3nEQRBADAEaSw6zC/EJkiwGPXbWtPxl2xCdSoeepS07jW8UgcHNurfHvUzogEq5xk hu507c3BarVjyWCJOylMNR98Yd8VqD9UfmX0Hb8/BrA+Hl6/DB/eqGptrf4BSRwcZQM32aZK 7Pj2XbGWIUrZrd70x1eAP9QE3P79Y2oLrsCgbZJfEwCgvz9JjGmQqQkRiTVzlZVCJYcyGGsD /0tbFCzD2h20ahe8rC1gbb3K3qk+LpBtvjBu1RY9drYk0NymiGbJWZgab6t1jM7sk2vuf0Py O9Hf9XBmK0uE9IgMaiCpc32XV9oASz6UJebwkX+zF2jG5I1BfnO9g7KlotcA/v5ClMjgo6Gl MDY4HxoSRu3i1cqqSDtVlt+AOVBJBACrZcnHAUSuCXBPy0jOlBhxPqRWv6ND4c9PH1xjQ3NP nxJuMBS8rnNg22uyfAgmBKNLpLgAGVRMZGaGoJObGf72s6TeIqKJo/LtggAS9qAUiuKVnygo 3wjfkS9A3DRO+SpU7JqWdsveeIQyeyEJ/8PTowmSQLakF+3fote9ybzd880fSmFuIEJldWxp Y2ggPGpiZXVsaWNoQHN1c2UuY29tPsJgBBMRAgAgBQJZN5xEAhsDBgsJCAcDAgQVAggDBBYC AwECHgECF4AACgkQoDSui/t3IH4J+wCfQ5jHdEjCRHj23O/5ttg9r9OIruwAn3103WUITZee e7Sbg12UgcQ5lv7SzsFNBFk3nEQQCACCuTjCjFOUdi5Nm244F+78kLghRcin/awv+IrTcIWF hUpSs1Y91iQQ7KItirz5uwCPlwejSJDQJLIS+QtJHaXDXeV6NI0Uef1hP20+y8qydDiVkv6l IreXjTb7DvksRgJNvCkWtYnlS3mYvQ9NzS9PhyALWbXnH6sIJd2O9lKS1Mrfq+y0IXCP10eS FFGg+Av3IQeFatkJAyju0PPthyTqxSI4lZYuJVPknzgaeuJv/2NccrPvmeDg6Coe7ZIeQ8Yj t0ARxu2xytAkkLCel1Lz1WLmwLstV30g80nkgZf/wr+/BXJW/oIvRlonUkxv+IbBM3dX2OV8 AmRv1ySWPTP7AAMFB/9PQK/VtlNUJvg8GXj9ootzrteGfVZVVT4XBJkfwBcpC/XcPzldjv+3 HYudvpdNK3lLujXeA5fLOH+Z/G9WBc5pFVSMocI71I8bT8lIAzreg0WvkWg5V2WZsUMlnDL9 mpwIGFhlbM3gfDMs7MPMu8YQRFVdUvtSpaAs8OFfGQ0ia3LGZcjA6Ik2+xcqscEJzNH+qh8V m5jjp28yZgaqTaRbg3M/+MTbMpicpZuqF4rnB0AQD12/3BNWDR6bmh+EkYSMcEIpQmBM51qM EKYTQGybRCjpnKHGOxG0rfFY1085mBDZCH5Kx0cl0HVJuQKC+dV2ZY5AqjcKwAxpE75MLFkr wkkEGBECAAkFAlk3nEQCGwwACgkQoDSui/t3IH7nnwCfcJWUDUFKdCsBH/E5d+0ZnMQi+G0A nAuWpQkjM1ASeQwSHEeAWPgskBQL In-Reply-To: <68c16600-a4bf-4060-a1fc-56c4ae655b03@suse.com> Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-720697/1785248578-F0CA22AC-5F56EB08/0/0 X-purgate-type: clean X-purgate-size: 10900 X-ZohoMail-DKIM: pass (identity @suse.com) X-ZM-MESSAGEID: 1785248597086158500 Content-Type: text/plain; charset="utf-8" The two functions are pretty similar, and hence changes commonly need to occur in both places. Fold the functions by introducing a new shared helper, which then will be used from the three relevant places. Note that this way preemptability can then be communicated down from shadow_set_allocation() right away. Signed-off-by: Jan Beulich --- To have the compiler eliminate the extra conditionals, should we make sh_blow_tables() always-inline? --- v14: New. --- a/xen/arch/x86/include/asm/perfc_defn.h +++ b/xen/arch/x86/include/asm/perfc_defn.h @@ -49,7 +49,8 @@ PERFCOUNTER(shadow_alloc_tlbflush, "shad /* STATUS counters do not reset when 'P' is hit */ PERFSTATUS(shadow_alloc_count, "number of shadow pages in use") PERFCOUNTER(shadow_free, "calls to shadow_free") -PERFCOUNTER(shadow_prealloc_1, "shadow recycles old shadows") +PERFCOUNTER(shadow_prealloc_0, "shadow recycles old shadows") +PERFCOUNTER(shadow_prealloc_1, "shadow recycles pinned shadows") PERFCOUNTER(shadow_prealloc_2, "shadow recycles in-use shadows") PERFCOUNTER(shadow_linear_map_failed, "shadow hit read-only linear map") PERFCOUNTER(shadow_a_update, "shadow A bit update") --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -370,79 +370,8 @@ static inline void trace_shadow_prealloc } } =20 -/* Make sure there are at least count order-sized pages - * available in the shadow page pool. */ -static bool __must_check _shadow_prealloc(struct domain *d, unsigned int p= ages) -{ - struct vcpu *v; - struct page_info *sp, *t; - mfn_t smfn; - int i; - - if ( d->arch.paging.free_pages >=3D pages ) - return true; - - if ( unlikely(d->is_dying) ) - /* No reclaim when the domain is dying, teardown will take care of= it. */ - return false; - - /* Nothing to reclaim when there are no vcpus yet. */ - if ( !d->vcpu[0] ) - return false; - - /* Stage one: walk the list of pinned pages, unpinning them */ - perfc_incr(shadow_prealloc_1); - foreach_pinned_shadow(d, sp, t) - { - smfn =3D page_to_mfn(sp); - - /* Unpin this top-level shadow */ - trace_shadow_prealloc_unpin(d, smfn); - sh_unpin(d, smfn); - - /* See if that freed up enough space */ - if ( d->arch.paging.free_pages >=3D pages ) - return true; - } - - /* Stage two: all shadow pages are in use in hierarchies that are - * loaded in cr3 on some vcpu. Walk them, unhooking the non-Xen - * mappings. */ - perfc_incr(shadow_prealloc_2); - - for_each_vcpu(d, v) - for ( i =3D 0; i < ARRAY_SIZE(v->arch.paging.shadow.shadow_table);= i++ ) - { - if ( !pagetable_is_null(v->arch.paging.shadow.shadow_table[i])= ) - { - TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_PREALLOC_UNHOOK); - shadow_unhook_mappings( - d, - pagetable_get_mfn(v->arch.paging.shadow.shadow_table[i= ]), - 0); - - /* See if that freed up enough space */ - if ( d->arch.paging.free_pages >=3D pages ) - { - guest_flush_tlb_mask(d, d->dirty_cpumask); - return true; - } - } - } - - /* Nothing more we can do: all remaining shadows are of pages that - * hold Xen mappings for some vcpu. This can never happen. */ - printk(XENLOG_ERR "Can't pre-allocate %u shadow pages!\n" - " shadow pages total =3D %u, free =3D %u, p2m=3D%u\n", - pages, d->arch.paging.total_pages, - d->arch.paging.free_pages, d->arch.paging.p2m_pages); - - ASSERT_UNREACHABLE(); - - guest_flush_tlb_mask(d, d->dirty_cpumask); - - return false; -} +static bool sh_blow_tables(struct domain *d, unsigned int goal, + bool *preempted); =20 /* Make sure there are at least count pages of the order according to * type available in the shadow page pool. @@ -466,7 +395,7 @@ bool shadow_prealloc(struct domain *d, u ((SHF_L1_ANY | SHF_FL1_ANY) & (1u << type)) ) count +=3D paging_logdirty_levels(); =20 - ret =3D _shadow_prealloc(d, count); + ret =3D sh_blow_tables(d, count, NULL); if ( !ret && (!d->is_shutting_down || d->shutdown_code !=3D SHUTDOWN_c= rash) ) /* * Failing to allocate memory required for shadow usage can only r= esult in @@ -477,9 +406,15 @@ bool shadow_prealloc(struct domain *d, u return ret; } =20 -/* Deliberately free all the memory we can: this will tear down all of - * this domain's shadows */ -void shadow_blow_tables(struct domain *d, bool *preempted) +/* + * When @goal is zero: Deliberately free all the memory we can: This will + * tear down all of this domain's shadows. + * + * When @goal is non-zero: Make sure there are at least as many pages + * available in the shadow page pool. + */ +static bool sh_blow_tables(struct domain *d, unsigned int goal, + bool *preempted) { struct page_info *sp, *t; struct vcpu *v; @@ -487,19 +422,25 @@ void shadow_blow_tables(struct domain *d int i; unsigned int done =3D 0; =20 + if ( goal && d->arch.paging.free_pages >=3D goal ) + return true; + /* * When the domain is dying a call to shadow_blow_tables() will be * performed from the teardown path with preemption support, ignore any * other calls as we want to do the final teardown with preemption sup= port. * Teardown of shadow related data can only be avoided when all domain * vCPUs are stopped. + * + * For the pre-allocation case, no reclaim when the domain is dying, + * teardown will take care of it. */ - if ( unlikely(d->is_dying) && !preempted ) - return; + if ( unlikely(d->is_dying) && (goal || !preempted) ) + return false; =20 /* Nothing to do when there are no vcpus yet. */ if ( !d->vcpu[0] ) - return; + return false; =20 /* First pass: reduce page table depth */ if ( preempted ) @@ -513,16 +454,23 @@ void shadow_blow_tables(struct domain *d #endif }; =20 + if ( goal ) + perfc_incr(shadow_prealloc_0); + HASH_CALLBACKS_CHECK(SHF_page_type_mask & ~(SHF_L1_ANY | SHF_FL1_A= NY)); =20 for ( i =3D 0; i < ARRAY_SIZE(masks); ++i ) { while ( hash_foreach(d, masks[i], callbacks, _mfn(0)) ) { + /* See if that freed up enough space */ + if ( goal && d->arch.paging.free_pages >=3D goal ) + return true; + if ( general_preempt_check() ) { *preempted =3D true; - return; + return false; } } } @@ -530,18 +478,31 @@ void shadow_blow_tables(struct domain *d } =20 /* Second pass: unpin all pinned pages */ + if ( goal ) + perfc_incr(shadow_prealloc_1); foreach_pinned_shadow(d, sp, t) { smfn =3D page_to_mfn(sp); + + /* Unpin this top-level shadow */ + if ( goal ) + trace_shadow_prealloc_unpin(d, smfn); sh_unpin(d, smfn); + + /* See if that freed up enough space */ + if ( goal && d->arch.paging.free_pages >=3D goal ) + return true; + if ( preempted && !(++done & 0xff) && general_preempt_check() ) { *preempted =3D true; - return; + return false; } } =20 /* Third pass: unhook entries of in-use shadows */ + if ( goal ) + perfc_incr(shadow_prealloc_2); for_each_vcpu(d, v) for ( i =3D 0; i < ARRAY_SIZE(v->arch.paging.shadow.shadow_table);= i++ ) if ( !pagetable_is_null(v->arch.paging.shadow.shadow_table[i])= ) @@ -549,11 +510,20 @@ void shadow_blow_tables(struct domain *d unsigned int num =3D d->arch.paging.total_pages - d->arch.paging.free_pages; =20 + if ( goal ) + TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_PREALLOC_UNHOOK); shadow_unhook_mappings( d, pagetable_get_mfn(v->arch.paging.shadow.shadow_table[i= ]), 0); =20 + /* See if that freed up enough space */ + if ( goal && d->arch.paging.free_pages >=3D goal ) + { + guest_flush_tlb_mask(d, d->dirty_cpumask); + return true; + } + /* * Make sure we are making progress before yielding: if do= main * is dying progress will be seen by total_pages decreasin= g, if @@ -573,9 +543,32 @@ void shadow_blow_tables(struct domain *d } } =20 + if ( goal ) + { + /* + * Nothing more we can do: All remaining shadows are of pages that + * hold Xen mappings for some vcpu. This can never happen. + */ + printk(XENLOG_ERR "Can't pre-allocate %u shadow pages!\n" + " shadow pages total =3D %u, free =3D %u, p2m=3D%u\n", + goal, d->arch.paging.total_pages, + d->arch.paging.free_pages, d->arch.paging.p2m_pages); + + ASSERT_UNREACHABLE(); + } + out: /* Make sure everyone sees the unshadowings */ guest_flush_tlb_mask(d, d->dirty_cpumask); + + return false; +} + +/* Deliberately free all the memory we can: this will tear down all of + * this domain's shadows */ +void shadow_blow_tables(struct domain *d, bool *preempted) +{ + sh_blow_tables(d, 0, preempted); } =20 void shadow_blow_tables_per_domain(struct domain *d) @@ -910,8 +903,8 @@ int shadow_set_allocation(struct domain else if ( d->arch.paging.total_pages > pages ) { /* Need to return memory to domheap */ - if ( !_shadow_prealloc(d, 1) ) - return -ENOMEM; + if ( !sh_blow_tables(d, 1, preempted) ) + return preempted && *preempted ? 0 : -ENOMEM; =20 sp =3D page_list_remove_head(&d->arch.paging.freelist); ASSERT(sp); @@ -2320,7 +2313,7 @@ void shadow_teardown(struct domain *d, b =20 /* * Reclaim all shadow memory so that shadow_set_allocation() doesn't f= ind - * in-use pages, as _shadow_prealloc() will no longer try to reclaim p= ages + * in-use pages, as sh_blow_tables() will no longer try to reclaim pag= es * because the domain is dying. */ paging_lock(d); From nobody Wed Aug 26 01:48:52 2026 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=quarantine dis=none) header.from=suse.com ARC-Seal: i=1; a=rsa-sha256; t=1785248628; cv=none; d=zohomail.com; s=zohoarc; b=Q6scTW7sm9yyQPaDuFPxfibScn4VyB8SEZ1hGlx9NYtrQqPSKcwoSXjRroV8bFuhFWgaFBpqvyWp82McTdvND9P43EYqjMvbfTpi+2Iu1jERDj74JTz78S8VXqQ4Y19U1zWnbslGFbAJEU47eWCjUAyiXirdqh/1niloawEcE44= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785248628; 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=w1o+lRjL5Bu7MJj4eoJSBjI4Yb8dSfa5/A/XYawdiOo=; b=BvROqoJTBYZQZeFbSToqvOG7pzKxl2Obo8UoMjrJ1h1EXNp+/H+DPVlsfTPdTXF8PLp5+88+P+hKKLUCCpaVdWOSJ2f6DSc/vgMIVw0ArUgRVcDJbZPAkond+5zPGP/kHHx/hzSbozApQ+Cvn6GnngkGyRy0m8lZXzaia1WgSrs= 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=quarantine dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 178524862869616.240841011961493; Tue, 28 Jul 2026 07:23:48 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1374405.1621567 (Exim 4.92) (envelope-from ) id 1woiiJ-0004Sy-7s; Tue, 28 Jul 2026 14:23:23 +0000 Received: by outflank-mailman (output) from mailman id 1374405.1621567; Tue, 28 Jul 2026 14:23:23 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1woiiJ-0004Sr-4x; Tue, 28 Jul 2026 14:23:23 +0000 Received: by outflank-mailman (input) for mailman id 1374405; Tue, 28 Jul 2026 14:23:21 +0000 Received: from mx.expurgate.net ([194.145.224.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1woiiH-0004SU-Ih for xen-devel@lists.xenproject.org; Tue, 28 Jul 2026 14:23:21 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1woiiG-007NWv-Vj for xen-devel@lists.xenproject.org; Tue, 28 Jul 2026 16:23:20 +0200 Received: from [10.42.69.4] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a68bb4c-e002-0a2a0a5209dd-0a2a4504d6e4-36 for ; Tue, 28 Jul 2026 16:23:20 +0200 Received: from [209.85.128.46] (helo=mail-wm1-f46.google.com) by tlsNG-ebf023.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a68bb58-b57f-0a2a45040019-d155802eecfd-3 for ; Tue, 28 Jul 2026 16:23:20 +0200 Received: by mail-wm1-f46.google.com with SMTP id 5b1f17b1804b1-4954dff6536so27607815e9.0 for ; Tue, 28 Jul 2026 07:23:20 -0700 (PDT) Received: from [10.156.60.236] (ip-037-024-206-209.um08.pools.vodafone-ip.de. [37.24.206.209]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4957f9ae5c3sm429559225e9.3.2026.07.28.07.23.19 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 28 Jul 2026 07:23:19 -0700 (PDT) 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" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=google header.d=suse.com header.i="@suse.com" header.h="Content-Transfer-Encoding:Content-Type:In-Reply-To:Autocrypt:Content-Language:References:Cc:To:From:Subject:User-Agent:MIME-Version:Date:Message-ID" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=google; t=1785248600; x=1785853400; darn=lists.xenproject.org; h=content-transfer-encoding:content-type:in-reply-to:autocrypt :content-language:references:cc:to:from:subject:user-agent :mime-version:date:message-id:from:to:cc:subject:date:message-id :reply-to:content-type; bh=w1o+lRjL5Bu7MJj4eoJSBjI4Yb8dSfa5/A/XYawdiOo=; b=JwW2JhE10m8PYeo+htnT6JIt8x135vxDxvQ4aMp0GfcK3iXsKGCEgILrgXO/GbEu8e 13O3BJkuVtCUHHV4LyBKu2ClN0ixVOytNtSEmYj84rglo0wG6xqETEzeGJyYi/XvT176 QmFlUh15r4WDKHpFxw2yu7t3BhUnMORtkWi2toKOpfkEYBkzYTdVkCZjGtd92yezaS7d 4+zthzFi0WOL1m2XJR8y8VQtQ0ZwvwcyHP7RxEtxNZXF9Rzeam4XyJ5eCwudG0ZmryfN hSETK2mqIj04WN48XzFUEzb1aCdZ8ckTSyw7Pp/d+F7y7aXNCnihkuwYx1GGpvq2q5x0 5f+w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785248600; x=1785853400; h=content-transfer-encoding:content-type:in-reply-to:autocrypt :content-language:references:cc:to:from:subject:user-agent :mime-version:date:message-id:x-gm-gg:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to:content-type; bh=w1o+lRjL5Bu7MJj4eoJSBjI4Yb8dSfa5/A/XYawdiOo=; b=RJNOW2TTmW4Ba4FUrs7n7nLu3nwIMwltO9NuJxgAlw5yY/tQ11iZ3GUPvOHuVH7/93 TO3/CyWB9gtx5FWk3Cq3gfZDwwBPrfyAX9VgQmDzWc2sNSpGqzisvlg4UNnwtI0D9zc2 qlHohE3thWZ0SlfUCR3+TzcO6MBDoId4s4ym/tHQLJR19qxT1kwyl81zCjqPwhqLPwiU RBwC+9msoigi4gO/9VbmuFuTkDbxO6QkKS/8FQgkFyREJkOKg8NRHhXM/eXDHevg+wDM usXU42xu5XEgEshdJIIr4VN04S/jL1/pxEPb+O466PqaSyMmuU8CnwByjd4S5U/+HCux kuCg== X-Gm-Message-State: AOJu0YyLn+t+eaf1GCFysH+m3q4hD1QiTNOIgWJGpoCXq9BbNMJD+fqa qHf9eYu9rvQH7s+Tnj2mwWmtgGRTypXTjrHlaqw1BMcuzXNzrW+Uy/CYQO7y5VRVmqK3sbCjSS+ Nf99Tqw== X-Gm-Gg: AR+sD12Gile6slctf56hUyW7xY2xlD6tHDf74ntgvluKxq9nIk1QJQz6eYAj+y1l5fh LLfdB97NidASbOpr0Y0EPiY3DvN/5JeuNnxaNl65NjnjRy4UwaUqT4nMZzW6wFn1owr6D1bm9+f 9TKqBQrFuPwzdKyrd66C8xbpP8cNJHLkvFGBh93eeChM+G01lcgAre+z+GyWLHv1mJO2w3KCMJJ vDQ8BQCEfSaofpFeM99CMV2najkhaSrBismv9HqnWLj7aSQMq/wlOVaz9y+Im5YoapzcJ7aQUrQ 5u/aLK4txDwTbLtYi6bVp4o2jinigTcdKnKcGMfBFHXCpJA4edvNy3oXEBZ0sSveCJa/EJHyk9T sbGO+xAbQXwXwTi20OM9+hV76OLlRKdWN1NO2x2ak4xW1W+uA9vLhc+42Q/FHk4nTforg0cxEfi y5khLg5OMr3R6rFu51LbIqV0rjvT5mrpg5w1h1DCwg+RbhWAqCheoO/IHi1tSg9j2mqLe1AAtMl k6c X-Received: by 2002:a05:600c:1d1b:b0:493:bb0:3b43 with SMTP id 5b1f17b1804b1-496c6426bc8mr31339625e9.2.1785248600381; Tue, 28 Jul 2026 07:23:20 -0700 (PDT) Message-ID: <0051a0fb-9ca7-4f90-960e-08e0898ea874@suse.com> Date: Tue, 28 Jul 2026 16:23:18 +0200 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: [PATCH v15 08/10] x86/shadow: make log-dirty mode enable/disable properly preemptable From: Jan Beulich To: "xen-devel@lists.xenproject.org" Cc: Andrew Cooper , Tim Deegan References: <68c16600-a4bf-4060-a1fc-56c4ae655b03@suse.com> Content-Language: en-US Autocrypt: addr=jbeulich@suse.com; keydata= xsDiBFk3nEQRBADAEaSw6zC/EJkiwGPXbWtPxl2xCdSoeepS07jW8UgcHNurfHvUzogEq5xk hu507c3BarVjyWCJOylMNR98Yd8VqD9UfmX0Hb8/BrA+Hl6/DB/eqGptrf4BSRwcZQM32aZK 7Pj2XbGWIUrZrd70x1eAP9QE3P79Y2oLrsCgbZJfEwCgvz9JjGmQqQkRiTVzlZVCJYcyGGsD /0tbFCzD2h20ahe8rC1gbb3K3qk+LpBtvjBu1RY9drYk0NymiGbJWZgab6t1jM7sk2vuf0Py O9Hf9XBmK0uE9IgMaiCpc32XV9oASz6UJebwkX+zF2jG5I1BfnO9g7KlotcA/v5ClMjgo6Gl MDY4HxoSRu3i1cqqSDtVlt+AOVBJBACrZcnHAUSuCXBPy0jOlBhxPqRWv6ND4c9PH1xjQ3NP nxJuMBS8rnNg22uyfAgmBKNLpLgAGVRMZGaGoJObGf72s6TeIqKJo/LtggAS9qAUiuKVnygo 3wjfkS9A3DRO+SpU7JqWdsveeIQyeyEJ/8PTowmSQLakF+3fote9ybzd880fSmFuIEJldWxp Y2ggPGpiZXVsaWNoQHN1c2UuY29tPsJgBBMRAgAgBQJZN5xEAhsDBgsJCAcDAgQVAggDBBYC AwECHgECF4AACgkQoDSui/t3IH4J+wCfQ5jHdEjCRHj23O/5ttg9r9OIruwAn3103WUITZee e7Sbg12UgcQ5lv7SzsFNBFk3nEQQCACCuTjCjFOUdi5Nm244F+78kLghRcin/awv+IrTcIWF hUpSs1Y91iQQ7KItirz5uwCPlwejSJDQJLIS+QtJHaXDXeV6NI0Uef1hP20+y8qydDiVkv6l IreXjTb7DvksRgJNvCkWtYnlS3mYvQ9NzS9PhyALWbXnH6sIJd2O9lKS1Mrfq+y0IXCP10eS FFGg+Av3IQeFatkJAyju0PPthyTqxSI4lZYuJVPknzgaeuJv/2NccrPvmeDg6Coe7ZIeQ8Yj t0ARxu2xytAkkLCel1Lz1WLmwLstV30g80nkgZf/wr+/BXJW/oIvRlonUkxv+IbBM3dX2OV8 AmRv1ySWPTP7AAMFB/9PQK/VtlNUJvg8GXj9ootzrteGfVZVVT4XBJkfwBcpC/XcPzldjv+3 HYudvpdNK3lLujXeA5fLOH+Z/G9WBc5pFVSMocI71I8bT8lIAzreg0WvkWg5V2WZsUMlnDL9 mpwIGFhlbM3gfDMs7MPMu8YQRFVdUvtSpaAs8OFfGQ0ia3LGZcjA6Ik2+xcqscEJzNH+qh8V m5jjp28yZgaqTaRbg3M/+MTbMpicpZuqF4rnB0AQD12/3BNWDR6bmh+EkYSMcEIpQmBM51qM EKYTQGybRCjpnKHGOxG0rfFY1085mBDZCH5Kx0cl0HVJuQKC+dV2ZY5AqjcKwAxpE75MLFkr wkkEGBECAAkFAlk3nEQCGwwACgkQoDSui/t3IH7nnwCfcJWUDUFKdCsBH/E5d+0ZnMQi+G0A nAuWpQkjM1ASeQwSHEeAWPgskBQL In-Reply-To: <68c16600-a4bf-4060-a1fc-56c4ae655b03@suse.com> Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-ebf023/1785248600-C2AC8B50-467A7E34/0/0 X-purgate-type: clean X-purgate-size: 6503 X-ZohoMail-DKIM: pass (identity @suse.com) X-ZM-MESSAGEID: 1785248629233158500 Content-Type: text/plain; charset="utf-8" Their calls to shadow_set_allocation() are the last missing piece. While it may seem a little odd, it actually turns out easier to deal with the continuation a level up from where the need for it was first recognized. Signed-off-by: Jan Beulich --- I think the point was raised before: It's questionable whether shadow_one_bit_enable(), upon error, should bring the allocation back down to zero. This is going to be especially bad for a domain which previously had shadow enabled already (which could be HVM or L1TF- affected PV). Even in shadow_one_bit_disable() it's not clear this is the best possible behavior - the pool may have been set to something larger than the default by the admin. For now I'm maintaining prior behavior, but of course things would end up simpler if we could just get rid of those set-to-zero operations (and then perhaps also on shadow_enable()'s similar error path); the possible caveat there would be that overall memory consumption may then appear to grow for people monitoring a system. Originally I was considering to further qualify the d->arch.paging.preempt.drop_allocation checks by passing further down the "resuming" flag, but for a well-behaved tool stack (which allows one shadow-op to finish before starting another one) there shouldn't be a difference. Thoughts? --- v14: New. --- a/xen/arch/x86/include/asm/domain.h +++ b/xen/arch/x86/include/asm/domain.h @@ -236,6 +236,7 @@ struct paging_domain { struct { const struct domain *dom; unsigned int op; + bool drop_allocation:1; union { struct { unsigned long done:PADDR_BITS - PAGE_SHIFT; --- a/xen/arch/x86/mm/paging.c +++ b/xen/arch/x86/mm/paging.c @@ -215,9 +215,10 @@ static int paging_log_dirty_enable(struc =20 paging_lock(d); =20 - if ( d->arch.paging.preempt.dom && - (d->arch.paging.preempt.dom !=3D current->domain || - d->arch.paging.preempt.op !=3D op) ) + if ( !d->arch.paging.preempt.dom ) + d->arch.paging.preempt.drop_allocation =3D false; + else if ( d->arch.paging.preempt.dom !=3D current->domain || + d->arch.paging.preempt.op !=3D op ) { paging_unlock(d); if ( !resuming ) @@ -259,9 +260,10 @@ static int paging_log_dirty_disable(stru =20 paging_lock(d); =20 - if ( d->arch.paging.preempt.dom && - (d->arch.paging.preempt.dom !=3D current->domain || - d->arch.paging.preempt.op !=3D XEN_DOMCTL_SHADOW_OP_OFF) ) + if ( !d->arch.paging.preempt.dom ) + d->arch.paging.preempt.drop_allocation =3D false; + else if ( d->arch.paging.preempt.dom !=3D current->domain || + d->arch.paging.preempt.op !=3D XEN_DOMCTL_SHADOW_OP_OFF ) { paging_unlock(d); if ( !resuming ) --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -2440,12 +2440,22 @@ static int shadow_one_bit_enable(struct =20 if ( d->arch.paging.total_pages < sh_min_allocation(d) ) { + bool preempted =3D false; + /* Init the shadow memory allocation if the user hasn't done so */ - if ( shadow_set_allocation(d, 1, NULL) !=3D 0 ) + if ( shadow_set_allocation(d, 1, + mode & PG_log_dirty ? &preempted + : NULL) !=3D 0 ) { - shadow_set_allocation(d, 0, NULL); - return -ENOMEM; + shadow_set_allocation(d, 0, + mode & PG_log_dirty ? &preempted : NULL); + if ( !preempted ) + return -ENOMEM; + d->arch.paging.preempt.drop_allocation =3D true; } + + if ( preempted ) + return -ERESTART; } =20 /* Allow p2m and log-dirty code to borrow shadow memory */ @@ -2484,6 +2494,8 @@ static int shadow_one_bit_disable(struct sh_new_mode(d, mode); if ( d->arch.paging.mode =3D=3D 0 ) { + bool preempted =3D false; + /* Get this domain off shadows */ SHADOW_PRINTK("un-shadowing of domain %u starts." " Shadow pages total =3D %u, free =3D %u, p2m=3D%u= \n", @@ -2511,8 +2523,16 @@ static int shadow_one_bit_disable(struct } =20 /* Pull down the memory allocation */ - if ( shadow_set_allocation(d, 0, NULL) !=3D 0 ) + if ( shadow_set_allocation(d, 0, + mode & PG_log_dirty ? &preempted + : NULL) !=3D 0 ) BUG(); /* In fact, we will have BUG()ed already */ + if ( preempted ) + { + d->arch.paging.preempt.drop_allocation =3D true; + return -ERESTART; + } + shadow_hash_teardown(d); SHADOW_PRINTK("un-shadowing of domain %u done." " Shadow pages total =3D %u, free =3D %u, p2m=3D%u= \n", @@ -2558,14 +2578,20 @@ static int shadow_test_disable(struct do */ static int cf_check sh_enable_log_dirty(struct domain *d) { + bool preempted =3D false; int ret; =20 ASSERT(paging_locked_by_me(d)); =20 - if ( shadow_mode_enabled(d) ) + if ( d->arch.paging.preempt.drop_allocation ) { - bool preempted =3D false; + shadow_set_allocation(d, 0, &preempted); =20 + return preempted ? -ERESTART : -ENOMEM; + } + + if ( shadow_mode_enabled(d) ) + { /* * This domain already has some shadows: need to clear them out * of the way to make sure that all references to guest memory are @@ -2598,6 +2624,21 @@ static int cf_check sh_disable_log_dirty =20 ASSERT(paging_locked_by_me(d)); =20 + if ( d->arch.paging.preempt.drop_allocation ) + { + shadow_set_allocation(d, 0, &preempted); + + if ( preempted ) + return -ERESTART; + + shadow_hash_teardown(d); + SHADOW_PRINTK("un-shadowing of domain %u done." + " Shadow pages total =3D %u, free =3D %u, p2m=3D%u= \n", + d->domain_id, d->arch.paging.total_pages, + d->arch.paging.free_pages, d->arch.paging.p2m_pages= ); + return 0; + } + /* * Limit the amount of work to do from sh_detach_old_tables() (called = from * shadow_one_bit_disable() via sh_new_mode() -> sh_update_paging_mode= s()), From nobody Wed Aug 26 01:48:52 2026 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=quarantine dis=none) header.from=suse.com ARC-Seal: i=1; a=rsa-sha256; t=1785248683; cv=none; d=zohomail.com; s=zohoarc; b=IffMsScazo90213U3jtpmt65huQxKWDqeSNrjX8cDwLwlXQwem9+1qcDL17ERHaaBt6k4HhV5KleKreQ/fPnOfzS4plHudFJ+S+fTGS1wiU3uhTlyvnUHCO3Pw7NjPHDWpx3T09APyZBJoS0lZTB3FqkopFyLzANlgN+UVWRWdg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785248683; 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=3lzZ7GYxAZkVGEZUpJdPRfH1NuosiuFuGkMMzSnec4o=; b=jse6cDL1T1boxKe9ryeXnNpNKTBdr7JQMhQ3HchuUYRFYqTiLdaq6JMj7nw1ievPS/4jHjC88sLudXAD0lyHOzv+4g1uZsxZTJKsJwOCBMBpiK/5uqvE/Gkr7d6SQybHkDN0GfDtfzIXjFcBJnsFr5n5LWEY2812rQgdt5qBQTk= 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=quarantine dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1785248683507901.6523420500583; Tue, 28 Jul 2026 07:24:43 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1374418.1621575 (Exim 4.92) (envelope-from ) id 1woijO-0005Cw-LT; Tue, 28 Jul 2026 14:24:30 +0000 Received: by outflank-mailman (output) from mailman id 1374418.1621575; Tue, 28 Jul 2026 14:24:30 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1woijO-0005Cn-Io; Tue, 28 Jul 2026 14:24:30 +0000 Received: by outflank-mailman (input) for mailman id 1374418; Tue, 28 Jul 2026 14:24:29 +0000 Received: from mx.expurgate.net ([194.145.224.20]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1woijN-0005Cf-KW for xen-devel@lists.xenproject.org; Tue, 28 Jul 2026 14:24:29 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1woijM-00F1g5-UP for xen-devel@lists.xenproject.org; Tue, 28 Jul 2026 16:24:28 +0200 Received: from [10.42.69.11] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a68bb95-2eae-0a2a0a5409dd-0a2a450bb4fa-18 for ; Tue, 28 Jul 2026 16:24:28 +0200 Received: from [209.85.221.49] (helo=mail-wr1-f49.google.com) by tlsNG-42698a.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a68bb9c-b7e8-0a2a450b0019-d155dd31a402-3 for ; Tue, 28 Jul 2026 16:24:28 +0200 Received: by mail-wr1-f49.google.com with SMTP id ffacd0b85a97d-4758bd3731bso970106f8f.0 for ; Tue, 28 Jul 2026 07:24:28 -0700 (PDT) Received: from [10.156.60.236] (ip-037-024-206-209.um08.pools.vodafone-ip.de. [37.24.206.209]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-47f85c7880dsm58999551f8f.37.2026.07.28.07.24.27 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 28 Jul 2026 07:24:27 -0700 (PDT) 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" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=google header.d=suse.com header.i="@suse.com" header.h="Content-Transfer-Encoding:Content-Type:In-Reply-To:Autocrypt:Content-Language:References:Cc:To:From:Subject:User-Agent:MIME-Version:Date:Message-ID" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=google; t=1785248668; x=1785853468; darn=lists.xenproject.org; h=content-transfer-encoding:content-type:in-reply-to:autocrypt :content-language:references:cc:to:from:subject:user-agent :mime-version:date:message-id:from:to:cc:subject:date:message-id :reply-to:content-type; bh=3lzZ7GYxAZkVGEZUpJdPRfH1NuosiuFuGkMMzSnec4o=; b=CH7/s/3o7uf7KReGiZ9e0vkmQdCS/HSAfL91+oPm2FmGXcbpXJXgDQsfzbnoCNBQ5k d0ouMlHRiZMtFXIdew75JHvu2Ani2Ovy5BloCmRmc2UxdECQd8CuZ1C994fHbQ2FQtip tWz3nRdxcmgBCWEREMh8be0wAoy4kSQvsBS6Y4oeBbTxC9R7QQvasZaNKsJnGtEAwFl8 e7DYt5F2/LgEY3cFf/AT7Kk45q8+QbT70CONUmaN+jOe6e8gU+YeRWnImD8bd9es8Ad7 vSqyF9ktHU3bMIfsbkqQcvXOIhQE/Mj0vJOYTkYtW8ZKhzlLEXb944TJBf8N5kctUKC8 M2YA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785248668; x=1785853468; h=content-transfer-encoding:content-type:in-reply-to:autocrypt :content-language:references:cc:to:from:subject:user-agent :mime-version:date:message-id:x-gm-gg:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to:content-type; bh=3lzZ7GYxAZkVGEZUpJdPRfH1NuosiuFuGkMMzSnec4o=; b=BL+heQHICeFH+R2GjvP9c9ryHHBzA2xZbjYuQJcHv3pGGZa4eqHYQGRDMhDdvT+p4/ 7vTN7UabheyDwNn8nFPuCBsFmLcBJ8YY3a12cLEMYySIeNX463ztiadwM/lVTa/P2Ds8 0U2SLkU6pI/nlov9KU3obv0bM5ByLG6UVUa/NFDE+QdYWD0zNb9s8Pipb+HVDlMt8oSk xevUcWvao75/fnaj79bIp7sGUALq/siMbgL3b8kMuS58GUfgxCJPrO8hmwUaOY9fyPOv HNTW3MdqtanTJF4nkas7RP4iu0GQJ12jN8ino6NWAMtS454Ej+iBDamMd8zVtgxAURbL 0A8A== X-Gm-Message-State: AOJu0YxNTOGz8yGn90s1QnUFkEAl8j1qHVr2T2K4+RLHbK8isZTIjUXM llLdOOOpVtOXU3dtUzDqQQC0AIs9w+DAeZyh38stap9xp0dtF24FQLTk8JFoFV4uQzpbkM/pCEb Uav/How== X-Gm-Gg: AR+sD11jLz22tZrByJVaUMvTEUB98+7R0gazqB8iuKg/bOIOzLMSM6ccO1fBZwgzK8D liEaqwz7/XRuk0BipxDEFTHOS+TpvuDMkbld9cPsYK2LxUP7b5VXMqaW1GIo0bassYpkED6D/w/ +I6N2rNaxl+KVR4Q/dEvxrjBC9EXCY4yU7CK2+vZCyoL9l+e8re2234g5C3vshu2wshxF39N601 oRIHQ0XMJO3pv9urf89ITBcNVpBEI7ui5bQ14y1vzp7tc+8rKPjplyJZhu75ZILhMRNXJKMYuSY b4tA6U0fkusfWJMRONgNXCmXq912ox6TpnNtli64u0M2r/aKmhB8Cd7ta3tpBJhbmuSh7h9sbcB kRhf4cI/PTE1h8i5KOGy/Aj3y/qI/7f8xHjnmjPVhpTLJoFieyuPbnOaBkZp+SgojbRjPUWfg0b CeXWrcLg8KVdySYTjMVcZTv5KTCsfFwCwURKcOGjEA4ON1nsp1fXuJN6Mhp1P1lIGNEw== X-Received: by 2002:adf:e19c:0:b0:47f:8282:42be with SMTP id ffacd0b85a97d-47fb1ecacaamr3144645f8f.18.1785248668204; Tue, 28 Jul 2026 07:24:28 -0700 (PDT) Message-ID: <0798cafd-50e9-4910-990e-37c64bfa59aa@suse.com> Date: Tue, 28 Jul 2026 16:24:27 +0200 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: [PATCH v15 09/10] x86/shadow: make forced (L1TF) mode enable properly preemptable From: Jan Beulich To: "xen-devel@lists.xenproject.org" Cc: Andrew Cooper , Tim Deegan References: <68c16600-a4bf-4060-a1fc-56c4ae655b03@suse.com> Content-Language: en-US Autocrypt: addr=jbeulich@suse.com; keydata= xsDiBFk3nEQRBADAEaSw6zC/EJkiwGPXbWtPxl2xCdSoeepS07jW8UgcHNurfHvUzogEq5xk hu507c3BarVjyWCJOylMNR98Yd8VqD9UfmX0Hb8/BrA+Hl6/DB/eqGptrf4BSRwcZQM32aZK 7Pj2XbGWIUrZrd70x1eAP9QE3P79Y2oLrsCgbZJfEwCgvz9JjGmQqQkRiTVzlZVCJYcyGGsD /0tbFCzD2h20ahe8rC1gbb3K3qk+LpBtvjBu1RY9drYk0NymiGbJWZgab6t1jM7sk2vuf0Py O9Hf9XBmK0uE9IgMaiCpc32XV9oASz6UJebwkX+zF2jG5I1BfnO9g7KlotcA/v5ClMjgo6Gl MDY4HxoSRu3i1cqqSDtVlt+AOVBJBACrZcnHAUSuCXBPy0jOlBhxPqRWv6ND4c9PH1xjQ3NP nxJuMBS8rnNg22uyfAgmBKNLpLgAGVRMZGaGoJObGf72s6TeIqKJo/LtggAS9qAUiuKVnygo 3wjfkS9A3DRO+SpU7JqWdsveeIQyeyEJ/8PTowmSQLakF+3fote9ybzd880fSmFuIEJldWxp Y2ggPGpiZXVsaWNoQHN1c2UuY29tPsJgBBMRAgAgBQJZN5xEAhsDBgsJCAcDAgQVAggDBBYC AwECHgECF4AACgkQoDSui/t3IH4J+wCfQ5jHdEjCRHj23O/5ttg9r9OIruwAn3103WUITZee e7Sbg12UgcQ5lv7SzsFNBFk3nEQQCACCuTjCjFOUdi5Nm244F+78kLghRcin/awv+IrTcIWF hUpSs1Y91iQQ7KItirz5uwCPlwejSJDQJLIS+QtJHaXDXeV6NI0Uef1hP20+y8qydDiVkv6l IreXjTb7DvksRgJNvCkWtYnlS3mYvQ9NzS9PhyALWbXnH6sIJd2O9lKS1Mrfq+y0IXCP10eS FFGg+Av3IQeFatkJAyju0PPthyTqxSI4lZYuJVPknzgaeuJv/2NccrPvmeDg6Coe7ZIeQ8Yj t0ARxu2xytAkkLCel1Lz1WLmwLstV30g80nkgZf/wr+/BXJW/oIvRlonUkxv+IbBM3dX2OV8 AmRv1ySWPTP7AAMFB/9PQK/VtlNUJvg8GXj9ootzrteGfVZVVT4XBJkfwBcpC/XcPzldjv+3 HYudvpdNK3lLujXeA5fLOH+Z/G9WBc5pFVSMocI71I8bT8lIAzreg0WvkWg5V2WZsUMlnDL9 mpwIGFhlbM3gfDMs7MPMu8YQRFVdUvtSpaAs8OFfGQ0ia3LGZcjA6Ik2+xcqscEJzNH+qh8V m5jjp28yZgaqTaRbg3M/+MTbMpicpZuqF4rnB0AQD12/3BNWDR6bmh+EkYSMcEIpQmBM51qM EKYTQGybRCjpnKHGOxG0rfFY1085mBDZCH5Kx0cl0HVJuQKC+dV2ZY5AqjcKwAxpE75MLFkr wkkEGBECAAkFAlk3nEQCGwwACgkQoDSui/t3IH7nnwCfcJWUDUFKdCsBH/E5d+0ZnMQi+G0A nAuWpQkjM1ASeQwSHEeAWPgskBQL In-Reply-To: <68c16600-a4bf-4060-a1fc-56c4ae655b03@suse.com> Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-42698a/1785248668-A8AC89EA-1A344F84/0/0 X-purgate-type: clean X-purgate-size: 5979 X-ZohoMail-DKIM: pass (identity @suse.com) X-ZM-MESSAGEID: 1785248685761158500 Content-Type: text/plain; charset="utf-8" Like for log-dirty enable/disable, reduce the amount of work to do underneath sh_new_mode() by calling shadow_blow_tables() (which is properly preemptable) up front. shadow_set_allocation() possibly taking long also is handled similar to log-dirty enable. Since this code runs inside a tasklet, carrying out preemption isn't straightforward; see the code comment. Signed-off-by: Jan Beulich --- The single-CPU case could of course do with improvement. Plus even on multi-CPU systems there will still be problems if there are enough domains all being switched to shadow mode at roughly the same time. Interaction with other shadow-op preemption is a little rough: Any attempt to issue a shadow-op (other than get-allocation) will result in -EBUSY while the operation here is still in progress. Notes from discussion: - if there weren't certain special situations (realtime scheduling requirem= ents, null scheduler, vCPU pinning), simply handling softirqs _only_ in the tasklet might be ok= ay - instead of doing shadow_blow_tables() and shadow_set_allocation() from th= e tasklet, we may be able to arrange doing that in the context of the initiating vCPU (with al= l other vCPU-s paused), scheduling the tasklet only once done, and making sure we don't fully exi= t back to guest context in the process (but enough to allow scheduling to occur) [Could we have p= aravirt_ctxt_switch_to() schedule a softirq-tasklet for VMs in transitional state, which then does= the work?] --- v14: New. --- a/xen/arch/x86/include/asm/domain.h +++ b/xen/arch/x86/include/asm/domain.h @@ -237,6 +237,7 @@ struct paging_domain { const struct domain *dom; unsigned int op; bool drop_allocation:1; + bool pv_l1tf_paused:1; union { struct { unsigned long done:PADDR_BITS - PAGE_SHIFT; --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -2444,11 +2445,11 @@ static int shadow_one_bit_enable(struct =20 /* Init the shadow memory allocation if the user hasn't done so */ if ( shadow_set_allocation(d, 1, - mode & PG_log_dirty ? &preempted - : NULL) !=3D 0 ) + mode & ~PG_SH_enable ? &preempted + : NULL) !=3D 0 ) { shadow_set_allocation(d, 0, - mode & PG_log_dirty ? &preempted : NULL); + mode & ~PG_SH_enable ? &preempted : NULL= ); if ( !preempted ) return -ENOMEM; d->arch.paging.preempt.drop_allocation =3D true; @@ -2785,22 +2786,80 @@ void shadow_audit_tables(struct vcpu *v) void cf_check pv_l1tf_tasklet(void *data) { struct domain *d =3D data; + int ret =3D 0; =20 - domain_pause(d); + /* Lock-less read is okay: The field is only written inside this taskl= et. */ + if ( !d->arch.paging.preempt.pv_l1tf_paused ) + domain_pause(d); paging_lock(d); =20 - if ( !paging_mode_sh_forced(d) && !d->is_dying ) + while ( !paging_mode_sh_forced(d) && !d->is_dying ) { - int ret =3D shadow_one_bit_enable(d, PG_SH_forced); + bool preempted =3D false; + unsigned int cpu, next; =20 - if ( ret ) + if ( !d->arch.paging.preempt.dom ) + { + d->arch.paging.preempt.dom =3D dom_xen; + d->arch.paging.preempt.drop_allocation =3D false; + } + + if ( unlikely(d->arch.paging.preempt.dom !=3D dom_xen) ) + { + /* Wait for other continuation to finish. */ + } + else if ( unlikely(d->arch.paging.preempt.drop_allocation) ) { - printk(XENLOG_G_ERR "d%d Failed to enable PG_SH_forced: %d\n", - d->domain_id, ret); - domain_crash(d); + ret =3D -ENOMEM; + shadow_set_allocation(d, 0, &preempted); + if ( !preempted ) + break; } + else + { + /* + * Limit the amount of work to do from sh_detach_old_tables() + * (called from shadow_one_bit_enable() via sh_new_mode() -> + * sh_update_paging_modes()), such that it doesn't also need to + * deal with preemption checks. + */ + shadow_blow_tables(d, &preempted); + if ( !preempted && + (ret =3D shadow_one_bit_enable(d, PG_SH_forced)) !=3D -ER= ESTART ) + break; + } + + d->arch.paging.preempt.pv_l1tf_paused =3D true; + paging_unlock(d); + + /* + * Crude "preemption" of a tasklet: To avoid hogging the local CPU, + * re-schedule the tasklet on another one. Unless of course there + * is none, in which case we will simply continue here. + */ + cpu =3D smp_processor_id(); + next =3D cpumask_cycle(cpu, &cpu_online_map); + if ( next !=3D cpu ) + { + tasklet_schedule_on_cpu(&d->arch.paging.shadow.pv_l1tf_tasklet, + next); + return; + } + + process_pending_softirqs(); + paging_lock(d); + } + + if ( ret ) + { + printk(XENLOG_G_ERR "%pd: Failed to enable PG_SH_forced: %d\n", + d, ret); + domain_crash(d); } =20 + d->arch.paging.preempt.dom =3D NULL; + d->arch.paging.preempt.drop_allocation =3D false; + d->arch.paging.preempt.pv_l1tf_paused =3D false; paging_unlock(d); domain_unpause(d); } From nobody Wed Aug 26 01:48:52 2026 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=quarantine dis=none) header.from=suse.com ARC-Seal: i=1; a=rsa-sha256; t=1785248711; cv=none; d=zohomail.com; s=zohoarc; b=PaD/19fwLbyKgLwrAJUWKC/yIEUD3QlrNZusiur2SwTBPL7+4ZDT9iHmw8U2WMwgIRAHDBKUvsk6KwxjvXB/EEh6wxsfgoIRo+BvKSY+9Dy3STasyCkhmeZp6D2cfvtxmj1w4A+p9ut6KayBQ5pqJdrzqAXO9AYsGb3HHtVITFk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785248711; 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=MDGxnQq9Xo0BHzcriwVqTJe+L979oWo8O6l6vHLNF/M=; b=cdEnB3yGcQAvOFzDHUTFsGmkf1kxOvZBjbvmbHaw718EOIssZQ2vFgv3wdadoEbbqbXlln0Jo2wbxoP/0/cOKkgXs4ujgHf8XupiUE++TnCPVIuz4H+mCOmQSCIg4uXaQwhmDYz4v2gRoKgvHsGG5qqzII5JJsQr6s1wjZn4wyg= 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=quarantine dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1785248711853957.6787327265926; Tue, 28 Jul 2026 07:25:11 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1374421.1621585 (Exim 4.92) (envelope-from ) id 1woiji-0005Zt-Tk; Tue, 28 Jul 2026 14:24:50 +0000 Received: by outflank-mailman (output) from mailman id 1374421.1621585; Tue, 28 Jul 2026 14:24:50 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1woiji-0005Zl-PW; Tue, 28 Jul 2026 14:24:50 +0000 Received: by outflank-mailman (input) for mailman id 1374421; Tue, 28 Jul 2026 14:24:49 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1woijh-0005YJ-IM for xen-devel@lists.xenproject.org; Tue, 28 Jul 2026 14:24:49 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1woijg-00Ee9J-VP for xen-devel@lists.xenproject.org; Tue, 28 Jul 2026 16:24:48 +0200 Received: from [10.42.69.5] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a68bb93-bab6-0a2a0a5309dd-0a2a4505ca28-42 for ; Tue, 28 Jul 2026 16:24:48 +0200 Received: from [209.85.128.51] (helo=mail-wm1-f51.google.com) by tlsNG-c201ff.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a68bbb0-4cb1-0a2a45050019-d1558033ecff-3 for ; Tue, 28 Jul 2026 16:24:48 +0200 Received: by mail-wm1-f51.google.com with SMTP id 5b1f17b1804b1-4954dff6536so27618075e9.0 for ; Tue, 28 Jul 2026 07:24:48 -0700 (PDT) Received: from [10.156.60.236] (ip-037-024-206-209.um08.pools.vodafone-ip.de. [37.24.206.209]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-47f85b9a64dsm64542593f8f.1.2026.07.28.07.24.47 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 28 Jul 2026 07:24:47 -0700 (PDT) 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" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=google header.d=suse.com header.i="@suse.com" header.h="Content-Transfer-Encoding:Content-Type:In-Reply-To:Autocrypt:Content-Language:References:Cc:To:From:Subject:User-Agent:MIME-Version:Date:Message-ID" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=google; t=1785248688; x=1785853488; darn=lists.xenproject.org; h=content-transfer-encoding:content-type:in-reply-to:autocrypt :content-language:references:cc:to:from:subject:user-agent :mime-version:date:message-id:from:to:cc:subject:date:message-id :reply-to:content-type; bh=MDGxnQq9Xo0BHzcriwVqTJe+L979oWo8O6l6vHLNF/M=; b=APhgNz0mnimzYWh1zBtPx6kIMPnOSrOM7oyVI1PHBzBx2AO6eZmoOPb4dwbIkxggqs kji3ljPbWK4Wu4k7wyG2txzjTvyriGbfJJiGOnTwVlVunQRfzxlEIfiZzk6WXk6OdpQi kcBSvXMPW7W2BXqxeatcXxHKhdZcMzn50Q3gvWvDMajMjZKImiOOWwiBoAejtXKEC791 SIc8Z7MFoc7s+vg1Xy3SgHmj0W5VcWYlqtDT4SFe9rwJ0XnUJmwDludWW4O8i37v1ORC PalkQQujxF/4XKXb4OfVzQrbEBantkACRIIE8G6rho2CFy2ihG2sqxpqGBYF7xdHaHN4 t4Ag== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785248688; x=1785853488; h=content-transfer-encoding:content-type:in-reply-to:autocrypt :content-language:references:cc:to:from:subject:user-agent :mime-version:date:message-id:x-gm-gg:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to:content-type; bh=MDGxnQq9Xo0BHzcriwVqTJe+L979oWo8O6l6vHLNF/M=; b=Kn9soMkf58G8p9XuLkU0XBDS767nJP86xNZwOxp4irYxGPzgxg7vye7wlSaR9M0Skx GNEcckszghr3TUaXSv35QumJiEvggyAlffbcZRzi8xqyk7HGcoZAWzSLY3OaUkRPh4Ym JKPJ/YcIWvV/IXGcdWpXtkuWbtLDlC8pWglSwqIootwkwkqQQOHpRNYtZs/3FggYq2PZ DiHYfUrbJNF+8+s5cwOERYUkCeGkB6u6xnCp71EIwC2NYXZqjrnvv5OizATCPzkL8m1g q+rVe9u0M0azWmOnnch+b32Q5aCLSEKuRnxw5zVwokuACIb2g1PvgvYOIw5Hnsfz1Xl4 vdTg== X-Gm-Message-State: AOJu0YxByfv42nUqmZ0d/oW1zOUYCj04iIp+5tf4SwijdDrbeLGQPmEO rqFqH6WgXuUqYOTYy1/cfrnHlzt5DoFbdcmWnh1i0tFb6vvFzYIiPDo4VSIBS6wM6d5p+HT1D6C m6NoFOg== X-Gm-Gg: AR+sD12FZXOheL5m1M/nwrG9LSAciN2NWUiO1jIHuHY9OvXtk8dymO2rYF3nmBZX04T CsXeWho5S2dqjaXXvXkhvQ5iWfZYTpAknT0AL8ZngI86d5U3fCM8ejK9X2RLtfeq9KiiSDfIRyt mIFoyEyuycR14UT5MgxFKz82EPQBW3/2oqgV/lXZL+heAQ+4t7j4aE8J11LMVSlxfH/c4s+i13u JPbwfWC67qyWe+5XZ7xqdfJLprSlhD+b9f7OGEgBdE2JcFObFjnhoToxUGuPFESYdoGNO68QNta YmVf7G13XaaTogpPPdyQmjdgeBCB82VIN2mdwXxufJlgeegVFWcqhd3Dj1voH7pekJrlFgkLjKs qrAK+qO1yMUSMCa/qVnTvIisGE1LjEgCD+WBiFrIPhic1DzzjbD3UVi3I+6d6n+S/fW/VFHXDTS pFIuU9sQ96jRJLbyq5Vq+hoYLpgMBFSopfr7k3AxdUlyUmf+IVyh7xdAQM39XOYXFEyQ== X-Received: by 2002:a05:600c:3b14:b0:492:3e69:a86f with SMTP id 5b1f17b1804b1-496c6426375mr29663455e9.1.1785248688238; Tue, 28 Jul 2026 07:24:48 -0700 (PDT) Message-ID: Date: Tue, 28 Jul 2026 16:24:47 +0200 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: [PATCH v15 10/10] x86/shadow: limit the number of pages which may be in use as shadows From: Jan Beulich To: "xen-devel@lists.xenproject.org" Cc: Andrew Cooper , Tim Deegan References: <68c16600-a4bf-4060-a1fc-56c4ae655b03@suse.com> Content-Language: en-US Autocrypt: addr=jbeulich@suse.com; keydata= xsDiBFk3nEQRBADAEaSw6zC/EJkiwGPXbWtPxl2xCdSoeepS07jW8UgcHNurfHvUzogEq5xk hu507c3BarVjyWCJOylMNR98Yd8VqD9UfmX0Hb8/BrA+Hl6/DB/eqGptrf4BSRwcZQM32aZK 7Pj2XbGWIUrZrd70x1eAP9QE3P79Y2oLrsCgbZJfEwCgvz9JjGmQqQkRiTVzlZVCJYcyGGsD /0tbFCzD2h20ahe8rC1gbb3K3qk+LpBtvjBu1RY9drYk0NymiGbJWZgab6t1jM7sk2vuf0Py O9Hf9XBmK0uE9IgMaiCpc32XV9oASz6UJebwkX+zF2jG5I1BfnO9g7KlotcA/v5ClMjgo6Gl MDY4HxoSRu3i1cqqSDtVlt+AOVBJBACrZcnHAUSuCXBPy0jOlBhxPqRWv6ND4c9PH1xjQ3NP nxJuMBS8rnNg22uyfAgmBKNLpLgAGVRMZGaGoJObGf72s6TeIqKJo/LtggAS9qAUiuKVnygo 3wjfkS9A3DRO+SpU7JqWdsveeIQyeyEJ/8PTowmSQLakF+3fote9ybzd880fSmFuIEJldWxp Y2ggPGpiZXVsaWNoQHN1c2UuY29tPsJgBBMRAgAgBQJZN5xEAhsDBgsJCAcDAgQVAggDBBYC AwECHgECF4AACgkQoDSui/t3IH4J+wCfQ5jHdEjCRHj23O/5ttg9r9OIruwAn3103WUITZee e7Sbg12UgcQ5lv7SzsFNBFk3nEQQCACCuTjCjFOUdi5Nm244F+78kLghRcin/awv+IrTcIWF hUpSs1Y91iQQ7KItirz5uwCPlwejSJDQJLIS+QtJHaXDXeV6NI0Uef1hP20+y8qydDiVkv6l IreXjTb7DvksRgJNvCkWtYnlS3mYvQ9NzS9PhyALWbXnH6sIJd2O9lKS1Mrfq+y0IXCP10eS FFGg+Av3IQeFatkJAyju0PPthyTqxSI4lZYuJVPknzgaeuJv/2NccrPvmeDg6Coe7ZIeQ8Yj t0ARxu2xytAkkLCel1Lz1WLmwLstV30g80nkgZf/wr+/BXJW/oIvRlonUkxv+IbBM3dX2OV8 AmRv1ySWPTP7AAMFB/9PQK/VtlNUJvg8GXj9ootzrteGfVZVVT4XBJkfwBcpC/XcPzldjv+3 HYudvpdNK3lLujXeA5fLOH+Z/G9WBc5pFVSMocI71I8bT8lIAzreg0WvkWg5V2WZsUMlnDL9 mpwIGFhlbM3gfDMs7MPMu8YQRFVdUvtSpaAs8OFfGQ0ia3LGZcjA6Ik2+xcqscEJzNH+qh8V m5jjp28yZgaqTaRbg3M/+MTbMpicpZuqF4rnB0AQD12/3BNWDR6bmh+EkYSMcEIpQmBM51qM EKYTQGybRCjpnKHGOxG0rfFY1085mBDZCH5Kx0cl0HVJuQKC+dV2ZY5AqjcKwAxpE75MLFkr wkkEGBECAAkFAlk3nEQCGwwACgkQoDSui/t3IH7nnwCfcJWUDUFKdCsBH/E5d+0ZnMQi+G0A nAuWpQkjM1ASeQwSHEeAWPgskBQL In-Reply-To: <68c16600-a4bf-4060-a1fc-56c4ae655b03@suse.com> Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-c201ff/1785248688-F72B32A1-A6C2A9CF/0/0 X-purgate-type: clean X-purgate-size: 8663 X-ZohoMail-DKIM: pass (identity @suse.com) X-ZM-MESSAGEID: 1785248714026158500 In order to bound the amount of work a single invocation of shadow_unhook_mappings() may be doing all in one go, constrain the number of pages which may be in use as shadows. To achieve that, simply adjust the "success" exit condition of _shadow_prealloc(), thus forcing removal of shadows not only when we're short of memory. Note that, depending on workload, this may have a severe effect on performance, due to the potentially much larger rate of thrashed shadows. In the context of "x86/shadow: account for log-dirty mode when pre- allocating" it is relevant to note that we will be too strict in sh_prealloc_okay() when log-dirty mode is enabled: Only part of the pages considered are actually to become shadows. But I think accepting this is better than further complicating the logic. Requested-by: Roger Pau Monn=C3=A9 Signed-off-by: Jan Beulich Acked-by: Tim Deegan --- What exactly we want the upper bound to be is up for discussion. This may need to go together with an upper limit on the number of vCPU-s we deem supportable in a (shadow) guest. Really 32-bit HVM guests have 3 monitor tables. But I think that not accounting for that in sh_prealloc_okay() is acceptable. How to correctly do such accounting there would be unclear anyway, as we mean to only take domain properties into account, whereas mode dependent properties are per-vCPU. Backporting note: The placement of the setting of the new per-domain field relies on d->max_vcpus being set right at domain creation. Hence this will need to move elsewhere for 4.11 and older (perhaps into shadow_set_allocation()'s "if ( pages > 0 )" block, conditional upon the value still being zero and max_vcpus already set). Backporting note: 1d3668664df7 ("x86/shadow: restrict OOS allocation to when it's really needed") is a necessary prereq for the respective part of sh_prealloc_okay(). --- v14: Re-base over XSA-427 and new earlier patches. Restrict allowance for monitor tables to HVM. Restrict allowance for OOS to when that's actually in use. v13: Prevent underflow in sh_prealloc_okay(). Re-base. v12: Re-base past the XSA-410 series. v11: Account for monitor tables and OOS snapshots in sh_prealloc_okay(). Calculate the (default) maximum value once during domain initialization, into a new per-domain field. v10: Extend commit message. v9: New. --- a/xen/arch/x86/include/asm/domain.h +++ b/xen/arch/x86/include/asm/domain.h @@ -108,6 +108,9 @@ void init_hypercall_page(struct domain * struct shadow_domain { #ifdef CONFIG_SHADOW_PAGING unsigned int opt_flags; /* runtime tunable optimizations on/of= f */ + + unsigned int max_pages; /* limit on the number of shadows in u= se */ + struct page_list_head pinned_shadows; =20 /* 1-to-1 map for use when HVM vcpus have paging disabled */ --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -96,6 +96,32 @@ int shadow_domain_init(struct domain *d) d->arch.paging.flush_tlb =3D shadow_flush_tlb; #endif =20 + /* + * Figure out the default for the highest acceptable quantity of shadow + * memory. This is because we need to bound the amount of work potenti= ally + * in need of doing by a single shadow_unhook_mappings() invocation. + */ + d->arch.paging.shadow.max_pages =3D 2048; + if ( d->max_vcpus > 8 ) + { + /* + * This is + * + * 128 * (max_vcpus + 8) + * max_vcpus * --------------------- + * max_vcpus + * + * suitably resolved, with the right side of the multiplication + * (when expressed as f(x)) satisfying + * f(8) =3D 256 + * lim f(x) =3D 128 + * x->=E2=88=9E + * i.e. continuous with the simpler case above and converging to + * shadow_min_acceptable_pages() for large values. + */ + d->arch.paging.shadow.max_pages =3D 128 * (d->max_vcpus + 8); + } + return 0; } =20 @@ -372,7 +398,7 @@ static inline void trace_shadow_prealloc } =20 static bool sh_blow_tables(struct domain *d, unsigned int goal, - bool *preempted); + unsigned int type, bool *preempted); =20 /* Make sure there are at least count pages of the order according to * type available in the shadow page pool. @@ -396,7 +422,7 @@ bool shadow_prealloc(struct domain *d, u ((SHF_L1_ANY | SHF_FL1_ANY) & (1u << type)) ) count +=3D paging_logdirty_levels(); =20 - ret =3D sh_blow_tables(d, count, NULL); + ret =3D sh_blow_tables(d, count, type, NULL); if ( !ret && (!d->is_shutting_down || d->shutdown_code !=3D SHUTDOWN_c= rash) ) /* * Failing to allocate memory required for shadow usage can only r= esult in @@ -408,6 +434,31 @@ bool shadow_prealloc(struct domain *d, u } =20 /* + * Check that + * - there are enough free pages, + * - there aren't too many pages in use as shadows already when about to m= ake + * a (set of) new shadow page(s). + */ +static bool sh_prealloc_okay(const struct domain *d, unsigned int goal, + unsigned int type) +{ + if ( d->arch.paging.free_pages < goal ) + return false; + + if ( type < SH_type_min_shadow || type > SH_type_max_shadow ) + return true; + + return d->arch.paging.total_pages - + (d->arch.paging.free_pages - goal) <=3D + d->arch.paging.shadow.max_pages + +#if (SHADOW_OPTIMIZATIONS & SHOPT_OUT_OF_SYNC) + (d->options & XEN_DOMCTL_CDF_oos_off ? 0 : SHADOW_OOS_PAGES) + +#endif + /* Allow for one monitor table per HVM vCPU. */ + paging_mode_external(d) * d->max_vcpus; +} + +/* * When @goal is zero: Deliberately free all the memory we can: This will * tear down all of this domain's shadows. * @@ -415,7 +466,7 @@ bool shadow_prealloc(struct domain *d, u * available in the shadow page pool. */ static bool sh_blow_tables(struct domain *d, unsigned int goal, - bool *preempted) + unsigned int type, bool *preempted) { struct page_info *sp, *t; struct vcpu *v; @@ -423,7 +474,7 @@ static bool sh_blow_tables(struct domain int i; unsigned int done =3D 0; =20 - if ( goal && d->arch.paging.free_pages >=3D goal ) + if ( goal && sh_prealloc_okay(d, goal, type) ) return true; =20 /* @@ -465,7 +516,7 @@ static bool sh_blow_tables(struct domain while ( hash_foreach(d, masks[i], callbacks, _mfn(0)) ) { /* See if that freed up enough space */ - if ( goal && d->arch.paging.free_pages >=3D goal ) + if ( goal && sh_prealloc_okay(d, goal, type) ) return true; =20 if ( general_preempt_check() ) @@ -491,7 +542,7 @@ static bool sh_blow_tables(struct domain sh_unpin(d, smfn); =20 /* See if that freed up enough space */ - if ( goal && d->arch.paging.free_pages >=3D goal ) + if ( goal && sh_prealloc_okay(d, goal, type) ) return true; =20 if ( preempted && !(++done & 0xff) && general_preempt_check() ) @@ -519,7 +570,7 @@ static bool sh_blow_tables(struct domain 0); =20 /* See if that freed up enough space */ - if ( goal && d->arch.paging.free_pages >=3D goal ) + if ( goal && sh_prealloc_okay(d, goal, type) ) { guest_flush_tlb_mask(d, d->dirty_cpumask); return true; @@ -569,7 +620,7 @@ static bool sh_blow_tables(struct domain * this domain's shadows */ void shadow_blow_tables(struct domain *d, bool *preempted) { - sh_blow_tables(d, 0, preempted); + sh_blow_tables(d, 0, SH_type_none, preempted); } =20 void shadow_blow_tables_per_domain(struct domain *d) @@ -904,7 +955,7 @@ int shadow_set_allocation(struct domain else if ( d->arch.paging.total_pages > pages ) { /* Need to return memory to domheap */ - if ( !sh_blow_tables(d, 1, preempted) ) + if ( !sh_blow_tables(d, 1, SH_type_none, preempted) ) return preempted && *preempted ? 0 : -ENOMEM; =20 sp =3D page_list_remove_head(&d->arch.paging.freelist);