Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Will Deacon <will@kernel.org>
To: Jean-Philippe Brucker <jean-philippe@linaro.org>
Cc: catalin.marinas@arm.com, steven.price@arm.com,
	suzuki.poulose@arm.com, linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH] arm64: mm: Support memory hotplug in a Realm
Date: Tue, 4 Nov 2025 14:12:21 +0000	[thread overview]
Message-ID: <aQoJxdEVoVqBKLPx@willie-the-truck> (raw)
In-Reply-To: <20251013150938.1428357-2-jean-philippe@linaro.org>

On Mon, Oct 13, 2025 at 04:09:39PM +0100, Jean-Philippe Brucker wrote:
> Call the RIPAS change functions when adding and removing memory to/from
> a Realm.
> 
> The host initiates hotplug and the guest uses a range of predefined
> guest-physical addresses to install the new memory blocks. This patch
> then switches the RIPAS of those blocks from EMPTY to RAM. The guest can
> then online the blocks and use them.
> 
> Unplug is initiated by the host as well. After offlining the blocks
> the guest removes the mapping, and this patch switches the RIPAS from
> RAM to EMPTY.
> 
> Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
> ---
> To test this with a CCA-enabled host and virtio-mem:
>     $ qemu-system-aarch64
>         -m 1G,maxmem=1T
>         -M confidential-guest-support=rme0 -object rme-guest,id=rme0
>         -object memory-backend-ram,id=mem0,size=1G
>         -device virtio-mem-pci,id=hpm0,memdev=mem0,node=0
>         ...
> 
> Make offlining more likely to succeed:
>     # echo online_movable > /sys/devices/system/memory/auto_online_blocks
> 
> Plug and unplug some memory (2M granule)
>     (qemu) qom-set hpm0 requested-size 1G
>     (qemu) qom-set hpm0 requested-size 256M
> 
> Or via ACPI hotplug (requires EDK2 with Realm support)
>     (qemu) object_add memory-backend-ram,id=mem1,size=1G
>     (qemu) device_add pc-dimm,id=dimm1,memdev=mem1
>     (qemu) device_del dimm1
>     (qemu) object_del mem1
> ---
>  arch/arm64/include/asm/rsi.h |  3 +++
>  arch/arm64/kernel/rsi.c      | 23 +++++++++++++++++++++++
>  arch/arm64/mm/mmu.c          | 11 +++++++++--
>  3 files changed, 35 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/rsi.h b/arch/arm64/include/asm/rsi.h
> index 88b50d660e85a..5ffc7e40a1f32 100644
> --- a/arch/arm64/include/asm/rsi.h
> +++ b/arch/arm64/include/asm/rsi.h
> @@ -18,6 +18,9 @@ void __init arm64_rsi_init(void);
>  
>  bool arm64_rsi_is_protected(phys_addr_t base, size_t size);
>  
> +int arm64_rsi_add_memory(phys_addr_t start, phys_addr_t end);
> +int arm64_rsi_remove_memory(phys_addr_t start, phys_addr_t end);
> +
>  static inline bool is_realm_world(void)
>  {
>  	return static_branch_unlikely(&rsi_present);
> diff --git a/arch/arm64/kernel/rsi.c b/arch/arm64/kernel/rsi.c
> index c64a06f58c0bc..b983b85f03dfb 100644
> --- a/arch/arm64/kernel/rsi.c
> +++ b/arch/arm64/kernel/rsi.c
> @@ -138,6 +138,29 @@ static int realm_ioremap_hook(phys_addr_t phys, size_t size, pgprot_t *prot)
>  	return 0;
>  }
>  
> +/*
> + * Convert a range of IPAs from EMPTY to RAM
> + */
> +int arm64_rsi_add_memory(phys_addr_t start, phys_addr_t end)
> +{
> +	if (!is_realm_world())
> +		return 0;
> +
> +	return rsi_set_memory_range_protected(start, end);
> +}
> +
> +/*
> + * Convert a range of IPAs from RAM to EMPTY. The pages will be wiped by
> + * UNDELEGATE before being returned to the host.
> + */
> +int arm64_rsi_remove_memory(phys_addr_t start, phys_addr_t end)
> +{
> +	if (!is_realm_world())
> +		return 0;
> +
> +	return rsi_set_memory_range_shared(start, end);
> +}

Probably worth having this in a header so that the static key can be
inlined for the common case where we're not in a realm.

> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index b8d37eb037fcc..095b094e8a82f 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -44,6 +44,7 @@
>  #include <asm/tlbflush.h>
>  #include <asm/pgalloc.h>
>  #include <asm/kfence.h>
> +#include <asm/rsi.h>
>  
>  #define NO_BLOCK_MAPPINGS	BIT(0)
>  #define NO_CONT_MAPPINGS	BIT(1)
> @@ -1874,6 +1875,10 @@ int arch_add_memory(int nid, u64 start, u64 size,
>  
>  	VM_BUG_ON(!mhp_range_allowed(start, size, true));
>  
> +	ret = arm64_rsi_add_memory(start, start + size);
> +	if (ret)
> +		return ret;
> +
>  	if (force_pte_mapping())
>  		flags |= NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
>  
> @@ -1885,10 +1890,11 @@ int arch_add_memory(int nid, u64 start, u64 size,
>  
>  	ret = __add_pages(nid, start >> PAGE_SHIFT, size >> PAGE_SHIFT,
>  			   params);
> -	if (ret)
> +	if (ret) {
>  		__remove_pgd_mapping(swapper_pg_dir,
>  				     __phys_to_virt(start), size);
> -	else {
> +		WARN_ON(arm64_rsi_remove_memory(start, start + size));
> +	} else {
>  		/* Address of hotplugged memory can be smaller */
>  		max_pfn = max(max_pfn, PFN_UP(start + size));
>  		max_low_pfn = max_pfn;
> @@ -1904,6 +1910,7 @@ void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap)
>  
>  	__remove_pages(start_pfn, nr_pages, altmap);
>  	__remove_pgd_mapping(swapper_pg_dir, __phys_to_virt(start), size);
> +	WARN_ON(arm64_rsi_remove_memory(start, start + size));

Hmm. This looks correct to me, but I wonder whether you've pushed the
rsi calls too far down? That is, I can understand this code being called
via virtio-mem and needing to transition the physical pages between
EMPTY/RAM, but these functions have other callers (e.g. via
memunmap_pages()) where it's not at all clear that the RMM should be
called.

Will


      reply	other threads:[~2025-11-04 14:12 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-13 15:09 [PATCH] arm64: mm: Support memory hotplug in a Realm Jean-Philippe Brucker
2025-11-04 14:12 ` Will Deacon [this message]

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=aQoJxdEVoVqBKLPx@willie-the-truck \
    --to=will@kernel.org \
    --cc=catalin.marinas@arm.com \
    --cc=jean-philippe@linaro.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=steven.price@arm.com \
    --cc=suzuki.poulose@arm.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox