All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Aneesh Kumar K.V (Arm)" <aneesh.kumar@kernel.org>
Cc: "Andrew Morton" <akpm@linux-foundation.org>,
	"Baoquan He" <baoquan.he@linux.dev>,
	"Mike Rapoport" <rppt@kernel.org>,
	"Pasha Tatashin" <pasha.tatashin@soleen.com>,
	"Pratyush Yadav" <pratyush@kernel.org>,
	"Catalin Marinas" <catalin.marinas@arm.com>,
	"Christian König" <christian.koenig@amd.com>,
	"Jason Gunthorpe" <jgg@ziepe.ca>,
	"Joerg Roedel" <joro@8bytes.org>, "Marc Zyngier" <maz@kernel.org>,
	"Marek Szyprowski" <m.szyprowski@samsung.com>,
	"Robin Murphy" <robin.murphy@arm.com>,
	"Steven Price" <steven.price@arm.com>,
	"Sumit Semwal" <sumit.semwal@linaro.org>,
	"Suzuki K Poulose" <suzuki.poulose@arm.com>,
	"Thomas Gleixner" <tglx@kernel.org>,
	"Will Deacon" <will@kernel.org>,
	"Russell King" <linux@armlinux.org.uk>,
	"Benjamin Gaignard" <benjamin.gaignard@collabora.com>,
	"Brian Starkey" <Brian.Starkey@arm.com>,
	"John Stultz" <jstultz@google.com>,
	"Mark Rutland" <mark.rutland@arm.com>,
	"Radu Rendec" <radu@rendec.net>,
	"T.J. Mercier" <tjmercier@google.com>,
	"Madhavan Srinivasan" <maddy@linux.ibm.com>,
	"Michael Ellerman" <mpe@ellerman.id.au>,
	"Nicholas Piggin" <npiggin@gmail.com>,
	"Christophe Leroy" <chleroy@kernel.org>,
	"Ritesh Harjani" <ritesh.list@gmail.com>,
	"Shrikanth Hegde" <sshegde@linux.ibm.com>,
	"Alexander Gordeev" <agordeev@linux.ibm.com>,
	"Gerald Schaefer" <gerald.schaefer@linux.ibm.com>,
	"Heiko Carstens" <hca@linux.ibm.com>,
	"Vasily Gorbik" <gor@linux.ibm.com>,
	"Christian Borntraeger" <borntraeger@linux.ibm.com>,
	"Sven Schnelle" <svens@linux.ibm.com>,
	"Ingo Molnar" <mingo@redhat.com>,
	"Borislav Petkov" <bp@alien8.de>,
	"Dave Hansen" <dave.hansen@linux.intel.com>,
	x86@kernel.org, "H . Peter Anvin" <hpa@zytor.com>,
	"Kiryl Shutsemau" <kas@kernel.org>,
	"Rick Edgecombe" <rick.p.edgecombe@intel.com>,
	"K . Y . Srinivasan" <kys@microsoft.com>,
	"Haiyang Zhang" <haiyangz@microsoft.com>,
	"Wei Liu" <wei.liu@kernel.org>,
	"Dexuan Cui" <decui@microsoft.com>,
	"Long Li" <longli@microsoft.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"Vitaly Kuznetsov" <vkuznets@redhat.com>,
	"Andy Lutomirski" <luto@kernel.org>,
	"Peter Zijlstra" <peterz@infradead.org>,
	dri-devel@lists.freedesktop.org, linux-mm@kvack.org,
	kvmarm@lists.linux.dev, "Oliver Upton" <oupton@kernel.org>,
	media-ci@linuxtv.org
Subject: Re: [PATCH v9 02/14] mm: Zero memory during shared memory transitions
Date: Thu, 05 Nov 2026 16:52:42 +0000	[thread overview]
Message-ID: <sashiko-outbox-199540@kernel.org> (raw)
In-Reply-To: <20261104164555.3555725-3-aneesh.kumar@kernel.org>

Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
- [Critical] x86/hyperv: premature zeroing in hv_vtom_clear_present() before transition
- [High] Drivers: hv: uninitialized SynIC pages in hv_alloc_page() on non-CoCo VMs
- [High] dma-pool: dirty cache lines left on linear alias by set_memory_decrypted()
- [Medium] x86/mm: set_memory_decrypted() zeroes legacy VGA VRAM/MMIO in VGA_MAP_MEM()
- [Medium] powerpc/pseries/svm: set_memory_decrypted() zeroes private page before sharing
--

commit 0a47431deefcabfb66f48104fa0c06cece49f6f0
Author: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>

mm: Zero memory during shared memory transitions

This commit moves memory zeroing into the architecture-specific
implementations of set_memory_decrypted() so each platform clears shared
memory at the appropriate point in the private-to-shared transition. It
also removes post-transition memset() calls from callers and keeps explicit
zeroing on paths where no transition takes place.

> diff --git a/arch/powerpc/platforms/pseries/svm.c b/arch/powerpc/platforms/pseries/svm.c
> index 7a403dbd35ee5..a344e094fe1c8 100644
> --- a/arch/powerpc/platforms/pseries/svm.c
> +++ b/arch/powerpc/platforms/pseries/svm.c
[ ... ]
> @@ -59,6 +60,7 @@ int set_memory_decrypted(unsigned long addr, int numpages)
>  	if (!PAGE_ALIGNED(addr))
>  		return -EINVAL;
>  
> +	memset((void *)addr, 0, (size_t)numpages << PAGE_SHIFT);
>  	uv_share_page(PHYS_PFN(__pa(addr)), numpages);
>  
>  	return 0;

[Severity: Medium]
Should the memset() in set_memory_decrypted() happen after uv_share_page()
rather than before it?

On PowerPC pSeries Secure VMs, memory is partitioned between secure memory
and normal hypervisor-accessible memory rather than shared in place. When
uv_share_page() is called, the Ultravisor unmaps the secure page and the
hypervisor sets pvt->skip_page_out = true in kvmppc_share_page() before
allocating a new normal page and mapping it into the guest:

arch/powerpc/kvm/book3s_hv_uvmem.c:kvmppc_share_page() {
	if (kvmppc_gfn_is_uvmem_pfn(gfn, kvm, &uvmem_pfn)) {
		uvmem_page = pfn_to_page(uvmem_pfn);
		pvt = uvmem_page->zone_device_data;
		pvt->skip_page_out = true;
		...
}

Zeroing addr before uv_share_page() writes zeros to the private secure page
that is immediately unmapped and discarded (and faults in a secure page first
if one was not yet populated), instead of zeroing the shared mapping after
the transition completes.

[ ... ]

> diff --git a/arch/x86/hyperv/ivm.c b/arch/x86/hyperv/ivm.c
> index 2ce4dfe534727..e9c7799a00943 100644
> --- a/arch/x86/hyperv/ivm.c
> +++ b/arch/x86/hyperv/ivm.c
> @@ -755,6 +755,10 @@ static int hv_mark_gpa_visibility(u16 count, const u64 pfn[],
>   */
>  static int hv_vtom_clear_present(unsigned long kbuffer, int pagecount, bool enc)
>  {
> +	if (!enc)
> +		memset((void *)kbuffer, 0,
> +		       (size_t)pagecount << PAGE_SHIFT);
> +
>  	return set_memory_np(kbuffer, pagecount);
>  }

[Severity: Critical]
As reported by Sashiko on RFC v8 [1], doesn't zeroing kbuffer in
hv_vtom_clear_present() clear the private mapping before the transition to
shared completes, leaving the final shared mapping unzeroed?

In hv_vtom_init(), hv_vtom_clear_present() is registered as
x86_platform.guest.enc_status_change_prepare, while
hv_vtom_set_host_visibility() is registered as
x86_platform.guest.enc_status_change_finish.

When set_memory_decrypted() runs on Hyper-V Isolation VMs using vTOM or a
paravisor, __set_memory_enc_pgtable() invokes the callbacks in this order:

__set_memory_enc_pgtable()
  -> hv_vtom_clear_present()          (prepare: kbuffer is still private)
  -> __change_page_attr_set_clr()     (updates PTEs with shared_gpa_boundary)
  -> hv_vtom_set_host_visibility()    (finish: marks GPA host-visible and
                                       restores _PAGE_PRESENT via
                                       set_memory_p())

Because memset() runs in hv_vtom_clear_present() while kbuffer still maps the
encrypted/private GPA below ms_hyperv.shared_gpa_boundary, the shared mapping
above vTOM is never zeroed after hv_vtom_set_host_visibility() makes the
pages host-visible and present again. With the post-transition memset() calls
removed from callers such as vmbus_connect(), hv_alloc_page(),
dma_direct_alloc(), dma_direct_alloc_pages(), and
__alloc_cc_shared_pages_node(), shared buffers on vTOM VMs will contain
ciphertext or uninitialized data instead of zeros.

Should this memset() be moved to the end of hv_vtom_set_host_visibility()
after set_memory_p() succeeds?

[ ... ]

> diff --git a/arch/x86/mm/mem_encrypt_amd.c b/arch/x86/mm/mem_encrypt_amd.c
> index 2f8c32173972d..a1199a74e9a3f 100644
> --- a/arch/x86/mm/mem_encrypt_amd.c
> +++ b/arch/x86/mm/mem_encrypt_amd.c
[ ... ]
> @@ -308,6 +309,9 @@ static int amd_enc_status_change_finish(unsigned long vaddr, int npages, bool en
>  	if (!cc_platform_has(CC_ATTR_HOST_MEM_ENCRYPT))
>  		enc_dec_hypercall(vaddr, npages << PAGE_SHIFT, enc);
>  
> +	if (!enc)
> +		memset((void *)vaddr, 0, (size_t)npages << PAGE_SHIFT);
> +
>  	return 0;
>  }

[Severity: Medium]
What happens during vgacon_startup() when VGA_MAP_MEM() calls
set_memory_decrypted() on the legacy VGA video memory range?

In arch/x86/include/asm/vga.h, VGA_MAP_MEM() calls set_memory_decrypted() on
the direct-map address of legacy VGA memory (0xb8000 or 0xb0000):

#define VGA_MAP_MEM(x, s)					\
({								\
	unsigned long start = (unsigned long)phys_to_virt(x);	\
								\
	if (IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT))			\
		set_memory_decrypted(start, (s) >> PAGE_SHIFT);	\
								\
	start;							\
})

During console initialization, con_init() -> vgacon_startup() calls
VGA_MAP_MEM(vga_vram_base, vga_vram_size) before probing for VGA hardware and
before vgacon_save_screen() saves the pre-boot screen contents.

With amd_enc_status_change_finish() and tdx_enc_status_change_finish() now
unconditionally calling memset() on !enc:

1. On AMD SME/SEV, set_memory_decrypted() wipes the 32 KiB VGA text buffer
   before vgacon_startup() checks the buffer or saves the initial screen.
2. On AMD SEV-ES/SEV-SNP and Intel TDX guests, 0xb8000-0xbffff is an MMIO
   range; executing memset() (which uses rep stosb when X86_FEATURE_FSRS is
   set) on that shared MMIO range triggers a #VC or #VE exception that
   insn_decode_mmio() cannot decode, panicking the kernel at boot.

[ ... ]

> diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
> index fe50090dcc011..6e836a02910a0 100644
> --- a/drivers/hv/hv.c
> +++ b/drivers/hv/hv.c
> @@ -123,12 +123,13 @@ static int hv_alloc_page(void **page, bool decrypt, const char *note)
>  	if (!*page)
>  		return -ENOMEM;
>  
> -	if (decrypt)
> +	if (decrypt) {
>  		ret = set_memory_decrypted((unsigned long)*page, 1);
> -	if (ret)
> -		goto failed;
> -
> -	memset(*page, 0, PAGE_SIZE);
> +		if (ret)
> +			goto failed;
> +	} else {
> +		memset(*page, 0, PAGE_SIZE);
> +	}
>  	return 0;
>  
>  failed:

[Severity: High]
As reported by Sashiko on RFC v8 [2], doesn't skipping memset() when decrypt
is true leave SynIC message and event pages uninitialized on standard
(non-CoCo) Hyper-V VMs?

In hv_synic_alloc(), decrypt is set to !vmbus_is_confidential():

drivers/hv/hv.c:hv_synic_alloc() {
	const bool decrypt = !vmbus_is_confidential();
	...
	if (!ms_hyperv.paravisor_present && !hv_root_partition()) {
		ret = hv_alloc_page(&hv_cpu->hyp_synic_message_page,
			decrypt, "hypervisor SynIC msg");
		if (ret)
			goto err;
		ret = hv_alloc_page(&hv_cpu->hyp_synic_event_page,
			decrypt, "hypervisor SynIC event");
		...
}

On a standard non-confidential Hyper-V guest, vmbus_is_confidential() is
false, so decrypt is true. However, on non-CoCo x86 and arm64 guests where
memory encryption is inactive, set_memory_decrypted() is a no-op that returns
0 without zeroing the page. Because hv_alloc_page() allocates the page with
__get_free_page(GFP_KERNEL) without __GFP_ZERO and skips the else branch when
decrypt is true, hyp_synic_message_page and hyp_synic_event_page are handed
to the hypervisor with uninitialized kernel memory, leaving non-zero garbage
in message slot headers (msg->header.message_type != HVMSG_NONE) and event
flags.

[ ... ]

> diff --git a/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c b/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c
> index 26fe9c3f22e36..7d922e0a28f96 100644
> --- a/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c
> +++ b/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c
[ ... ]
> @@ -61,6 +62,8 @@ static int pkvm_set_memory_encrypted(unsigned long addr, int numpages)
>  
>  static int pkvm_set_memory_decrypted(unsigned long addr, int numpages)
>  {
> +	memset((void *)addr, 0, (size_t)numpages << PAGE_SHIFT);
> +
>  	return __set_memory_range(ARM_SMCCC_VENDOR_HYP_KVM_MEM_SHARE_FUNC_ID,
>  				  addr, numpages);
>  }

[Severity: High]
When atomic_pool_expand() expands a CoCo atomic DMA pool on arm64 (both here
in pkvm_set_memory_decrypted() and in realm_set_memory_decrypted()), doesn't
zeroing via the cacheable linear map allocate dirty cache lines after
arch_dma_prep_coherent() has already cleaned the cache?

In kernel/dma/pool.c:atomic_pool_expand(), arch_dma_prep_coherent() and the
non-cacheable vmap remap happen before set_memory_decrypted() is called on
page_to_virt(page):

kernel/dma/pool.c:atomic_pool_expand() {
	...
	arch_dma_prep_coherent(page, pool_size);

#ifdef CONFIG_DMA_DIRECT_REMAP
	if (dma_pool->cc_shared)
		prot = pgprot_decrypted(pgprot_dmacoherent(PAGE_KERNEL));
	else
		prot = pgprot_dmacoherent(PAGE_KERNEL);

	addr = dma_common_contiguous_remap(page, pool_size, prot,
			__builtin_return_address(0));
	if (!addr)
		goto free_page;
#else
	addr = page_to_virt(page);
#endif
	if (dma_pool->cc_shared) {
		ret = set_memory_decrypted((unsigned long)page_to_virt(page),
					   1 << order);
		...
}

Because pkvm_set_memory_decrypted() and realm_set_memory_decrypted() execute
memset() through the cacheable linear mapping page_to_virt(page) after
arch_dma_prep_coherent() has already run, dirty zeroed cache lines remain in
the CPU data cache for the linear alias while consumers of the atomic pool
access the buffer through the non-cacheable vmap alias addr or via device
DMA. If those dirty cache lines are later evicted, won't they overwrite data
written via the non-cacheable mapping or by DMA?

[1] https://lore.kernel.org/r/20260924100529.1398790-3-aneesh.kumar@kernel.org
[2] https://lore.kernel.org/r/20260924100529.1398790-3-aneesh.kumar@kernel.org

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261104164555.3555725-1-aneesh.kumar@kernel.org?part=2

  reply	other threads:[~2026-11-05 16:52 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-04 16:45 [PATCH v9 00/14] coco: guest: Add a shared-granule allocator for host-shared memory Aneesh Kumar K.V (Arm)
2026-11-04 16:45 ` [PATCH v9 01/14] mm: Add an allocator for CoCo shared memory Aneesh Kumar K.V (Arm)
2026-11-05 16:52   ` sashiko-bot
2026-11-12 16:49     ` Aneesh Kumar K.V
2026-11-06 14:41   ` Suzuki K Poulose
2026-11-06 15:30     ` Aneesh Kumar K.V
2026-11-06 15:34       ` Suzuki K Poulose
2026-11-04 16:45 ` [PATCH v9 02/14] mm: Zero memory during shared memory transitions Aneesh Kumar K.V (Arm)
2026-11-05 16:52   ` sashiko-bot [this message]
2026-11-12 17:29     ` Aneesh Kumar K.V
2026-11-04 16:45 ` [PATCH v9 03/14] irqchip/gic-v3-its: Resolve the default NUMA node explicitly Aneesh Kumar K.V (Arm)
2026-11-04 16:45 ` [PATCH v9 04/14] irqchip/gic-v3-its: Allocate shared tables using CoCo shared memory allocator Aneesh Kumar K.V (Arm)
2026-11-04 16:45 ` [PATCH v9 05/14] dma-contiguous: Derive shared alignment from DMA attributes Aneesh Kumar K.V (Arm)
2026-11-04 16:45 ` [PATCH v9 06/14] dma-pool: Allocate CoCo atomic pools using CoCo shared memory allocator Aneesh Kumar K.V (Arm)
2026-11-05 16:52   ` sashiko-bot
2026-11-04 16:45 ` [PATCH v9 07/14] dma-direct: Align CoCo shared DMA allocations to the shared granule size Aneesh Kumar K.V (Arm)
2026-11-04 16:45 ` [PATCH v9 08/14] swiotlb: Align shared IO TLB pools " Aneesh Kumar K.V (Arm)
2026-11-05 16:52   ` sashiko-bot
2026-11-04 16:45 ` [PATCH v9 09/14] swiotlb: Reject misaligned restricted DMA pools for CoCo guests Aneesh Kumar K.V (Arm)
2026-11-04 16:45 ` [PATCH v9 10/14] dma-buf: system_heap: Limit scatterlist entries to the buffer size Aneesh Kumar K.V (Arm)
2026-11-04 16:45 ` [PATCH v9 11/14] dma-buf: system_heap: Allocate shared buffers using CoCo shared memory allocator Aneesh Kumar K.V (Arm)
2026-11-04 16:45 ` [PATCH v9 12/14] swiotlb: Make rounded shared pool capacity allocatable Aneesh Kumar K.V (Arm)
2026-11-04 16:45 ` [PATCH v9 13/14] mm: Assert CoCo shared allocations may sleep Aneesh Kumar K.V (Arm)
2026-11-04 16:45 ` [PATCH v9 14/14] irqchip/gic-v3-its: Preallocate VPE L1 tables Aneesh Kumar K.V (Arm)
2026-11-05 16:20   ` Marc Zyngier
2026-11-06 15:45     ` Aneesh Kumar K.V
2026-11-12 22:22       ` Marc Zyngier
2026-11-05 16:52   ` sashiko-bot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-199540@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=Brian.Starkey@arm.com \
    --cc=agordeev@linux.ibm.com \
    --cc=akpm@linux-foundation.org \
    --cc=aneesh.kumar@kernel.org \
    --cc=baoquan.he@linux.dev \
    --cc=benjamin.gaignard@collabora.com \
    --cc=borntraeger@linux.ibm.com \
    --cc=bp@alien8.de \
    --cc=catalin.marinas@arm.com \
    --cc=chleroy@kernel.org \
    --cc=christian.koenig@amd.com \
    --cc=dave.hansen@linux.intel.com \
    --cc=decui@microsoft.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=gerald.schaefer@linux.ibm.com \
    --cc=gor@linux.ibm.com \
    --cc=haiyangz@microsoft.com \
    --cc=hca@linux.ibm.com \
    --cc=hpa@zytor.com \
    --cc=jgg@ziepe.ca \
    --cc=joro@8bytes.org \
    --cc=jstultz@google.com \
    --cc=kas@kernel.org \
    --cc=kvmarm@lists.linux.dev \
    --cc=kys@microsoft.com \
    --cc=linux-mm@kvack.org \
    --cc=linux@armlinux.org.uk \
    --cc=longli@microsoft.com \
    --cc=luto@kernel.org \
    --cc=m.szyprowski@samsung.com \
    --cc=maddy@linux.ibm.com \
    --cc=mark.rutland@arm.com \
    --cc=maz@kernel.org \
    --cc=media-ci@linuxtv.org \
    --cc=mingo@redhat.com \
    --cc=mpe@ellerman.id.au \
    --cc=npiggin@gmail.com \
    --cc=oupton@kernel.org \
    --cc=pasha.tatashin@soleen.com \
    --cc=pbonzini@redhat.com \
    --cc=peterz@infradead.org \
    --cc=pratyush@kernel.org \
    --cc=radu@rendec.net \
    --cc=rick.p.edgecombe@intel.com \
    --cc=ritesh.list@gmail.com \
    --cc=robin.murphy@arm.com \
    --cc=rppt@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=sshegde@linux.ibm.com \
    --cc=steven.price@arm.com \
    --cc=sumit.semwal@linaro.org \
    --cc=suzuki.poulose@arm.com \
    --cc=svens@linux.ibm.com \
    --cc=tglx@kernel.org \
    --cc=tjmercier@google.com \
    --cc=vkuznets@redhat.com \
    --cc=wei.liu@kernel.org \
    --cc=will@kernel.org \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.