* [PATCH v2] s390/mm: Allow hugepage migration for s390
@ 2026-11-11 18:29 Gerald Schaefer
2026-11-11 19:14 ` sashiko-bot
2026-11-12 7:54 ` Alexander Gordeev
0 siblings, 2 replies; 4+ messages in thread
From: Gerald Schaefer @ 2026-11-11 18:29 UTC (permalink / raw)
To: linux-s390
Cc: Alexander Gordeev, Heiko Carstens, Christian Borntraeger,
Ilya Leoshkevich
After hugetlbfs PTE_MARKER support for s390 introduced region-third
and segment table swap entries, it is possible to also allow hugepage
migration for s390.
This fixes the problem that hugetlbfs pages could not be allocated
from ZONE_MOVABLE memory, which is often used in combination with
memory hotplug. Therefore, without support for hugepage migration,
a large portion of system memory could be unavailable for hugetlbfs
page allocations.
Besides selecting ARCH_ENABLE_HUGEPAGE_MIGRATION, this only requires
definition of arch_hugetlb_migration_supported(), which can make use
of the existing arch_hugetlb_valid_size() function, similar to other
architectures.
Signed-off-by: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
---
arch/s390/Kconfig | 1 +
arch/s390/include/asm/hugetlb.h | 5 +++++
arch/s390/mm/hugetlbpage.c | 14 +++++++++++++-
3 files changed, 19 insertions(+), 1 deletion(-)
---
Changes in v2:
- Use "#if IS_ENABLED()" instead of "#ifdef" in
arch/s390/mm/hugetlbpage.c
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 612885228824..e3a704f423f3 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -83,6 +83,7 @@ config S390
select ALTERNATE_USER_ADDRESS_SPACE
select ARCH_32BIT_USTAT_F_TINODE
select ARCH_CORRECT_STACKTRACE_ON_KRETPROBE
+ select ARCH_ENABLE_HUGEPAGE_MIGRATION if HUGETLB_PAGE && MIGRATION
select ARCH_ENABLE_MEMORY_HOTPLUG if SPARSEMEM
select ARCH_ENABLE_SPLIT_PMD_PTLOCK if PGTABLE_LEVELS > 2
select ARCH_HAS_PMD_SOFTLEAVES if TRANSPARENT_HUGEPAGE
diff --git a/arch/s390/include/asm/hugetlb.h b/arch/s390/include/asm/hugetlb.h
index aea754b67c89..356a18a75d99 100644
--- a/arch/s390/include/asm/hugetlb.h
+++ b/arch/s390/include/asm/hugetlb.h
@@ -17,6 +17,11 @@
#define hugepages_supported() cpu_has_edat1()
+#ifdef CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION
+bool arch_hugetlb_migration_supported(struct hstate *h);
+#define arch_hugetlb_migration_supported arch_hugetlb_migration_supported
+#endif
+
#define __HAVE_ARCH_HUGE_SET_HUGE_PTE_AT
void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, pte_t pte, unsigned long sz);
diff --git a/arch/s390/mm/hugetlbpage.c b/arch/s390/mm/hugetlbpage.c
index f84aa9265430..2c6e94888bd0 100644
--- a/arch/s390/mm/hugetlbpage.c
+++ b/arch/s390/mm/hugetlbpage.c
@@ -224,7 +224,7 @@ pte_t *huge_pte_offset(struct mm_struct *mm,
return (pte_t *) pmdp;
}
-bool __init arch_hugetlb_valid_size(unsigned long size)
+static bool __hugetlb_valid_size(unsigned long size)
{
if (cpu_has_edat1() && size == PMD_SIZE)
return true;
@@ -241,3 +241,15 @@ unsigned int __init arch_hugetlb_cma_order(void)
return 0;
}
+
+bool __init arch_hugetlb_valid_size(unsigned long size)
+{
+ return __hugetlb_valid_size(size);
+}
+
+#if IS_ENABLED(CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION)
+bool arch_hugetlb_migration_supported(struct hstate *h)
+{
+ return __hugetlb_valid_size(huge_page_size(h));
+}
+#endif
--
2.53.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v2] s390/mm: Allow hugepage migration for s390
2026-11-11 18:29 [PATCH v2] s390/mm: Allow hugepage migration for s390 Gerald Schaefer
@ 2026-11-11 19:14 ` sashiko-bot
2026-11-12 11:13 ` Gerald Schaefer
2026-11-12 7:54 ` Alexander Gordeev
1 sibling, 1 reply; 4+ messages in thread
From: sashiko-bot @ 2026-11-11 19:14 UTC (permalink / raw)
To: Gerald Schaefer, linux-s390
Cc: Heiko Carstens, Vasily Gorbik, Alexander Gordeev,
Christian Borntraeger
Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [High] s390/mm: guest storage key loss on 1M/2G hugetlbfs page
migration
- [Medium] s390/mm: loss of soft-dirty bit in __pte_to_rste() and
__rste_to_pte() on hugetlb migration
--
commit d03e5331e4e0b88aa75246fc7dc6aef18e7c8cdd
Author: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
s390/mm: Allow hugepage migration for s390
This commit selects ARCH_ENABLE_HUGEPAGE_MIGRATION on s390 and defines
arch_hugetlb_migration_supported() for 1M and 2G hugepages so hugetlbfs
pages can be migrated and allocated from ZONE_MOVABLE.
> diff --git a/arch/s390/mm/hugetlbpage.c b/arch/s390/mm/hugetlbpage.c
> index f84aa9265430f..2c6e94888bd06 100644
> --- a/arch/s390/mm/hugetlbpage.c
> +++ b/arch/s390/mm/hugetlbpage.c
> @@ -224,7 +224,7 @@ pte_t *huge_pte_offset(struct mm_struct *mm,
> return (pte_t *) pmdp;
> }
>
> -bool __init arch_hugetlb_valid_size(unsigned long size)
> +static bool __hugetlb_valid_size(unsigned long size)
> {
> if (cpu_has_edat1() && size == PMD_SIZE)
> return true;
> @@ -241,3 +241,15 @@ unsigned int __init arch_hugetlb_cma_order(void)
>
> return 0;
> }
> +
> +bool __init arch_hugetlb_valid_size(unsigned long size)
> +{
> + return __hugetlb_valid_size(size);
> +}
> +
> +#if IS_ENABLED(CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION)
> +bool arch_hugetlb_migration_supported(struct hstate *h)
> +{
> + return __hugetlb_valid_size(huge_page_size(h));
> +}
> +#endif
[Severity: High]
Does migrating a 1M or 2G hugetlbfs folio backing a KVM guest lose the
guest's hardware storage keys?
For 1M and 2G mappings (KVM_CAP_S390_HPAGE_1M / KVM_CAP_S390_HPAGE_2G),
the KVM gmap uses large leaf CRSTEs without PGSTEs, and guest storage keys
live only in the physical page frames. When unmap_and_move_hugetlb_folio()
unmaps the folio via mmu_notifier_invalidate_range_start(),
_gmap_unmap_crste() clears the large CRSTE to _CRSTE_EMPTY without saving
or splitting the hardware storage keys:
arch/s390/kvm/gmap/gmap.c:_gmap_unmap_crste() {
...
if (!old.h.fc)
return 0;
if (old.s.fc1.pr && test_bit(GMAP_FLAG_EXPORT_ON_UNMAP, &priv->gmap->flags))
folio = phys_to_folio(crste_origin_large(old));
ok = gmap_crstep_xchg_atomic(priv->gmap, crstep, old, _CRSTE_EMPTY(old.h.tt), gfn);
...
}
folio_copy() -> copy_highpage() -> copy_page() then copies only the 4K
page contents via mvcl and does not copy the hardware storage keys to the
destination frames, leaving the guest with stale storage keys and causing
guest protection exceptions or memory corruption.
[Severity: Medium]
Does migrating a hugetlbfs page also drop its soft-dirty bit in
__pte_to_rste() and __rste_to_pte()?
When try_to_migrate_one() installs a hugetlb migration entry, it sets
_PAGE_SOFT_DIRTY via pte_swp_mksoft_dirty() and calls set_huge_pte_at().
However, the swap entry branches in __pte_to_rste() and __rste_to_pte() do
not transfer _PAGE_SOFT_DIRTY to and from _SEGMENT_ENTRY_SOFT_DIRTY:
arch/s390/mm/hugetlbpage.c:__pte_to_rste() {
...
} else if (!pte_none(pte)) {
/* swap pte */
arch_entry = __pte_to_swp_entry(pte);
rste = mk_swap_rste(__swp_type(arch_entry), __swp_offset(arch_entry));
...
}
arch/s390/mm/hugetlbpage.c:__rste_to_pte() {
...
} else if (!none) {
/* swap rste */
arch_entry = __rste_to_swp_entry(rste);
pte = mk_swap_pte(__swp_type_rste(arch_entry), __swp_offset_rste(arch_entry));
pteval = pte_val(pte);
...
}
As a result, remove_migration_pte() reads back old_pte via huge_ptep_get()
with pte_swp_soft_dirty(old_pte) == 0 and clears _PAGE_SOFT_DIRTY on the
restored hugepage PTE, breaking soft-dirty tracking via /proc/pid/pagemap.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261111182944.4154805-1-gerald.schaefer@linux.ibm.com?part=1
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2] s390/mm: Allow hugepage migration for s390
2026-11-11 18:29 [PATCH v2] s390/mm: Allow hugepage migration for s390 Gerald Schaefer
2026-11-11 19:14 ` sashiko-bot
@ 2026-11-12 7:54 ` Alexander Gordeev
1 sibling, 0 replies; 4+ messages in thread
From: Alexander Gordeev @ 2026-11-12 7:54 UTC (permalink / raw)
To: Gerald Schaefer
Cc: linux-s390, Heiko Carstens, Christian Borntraeger,
Ilya Leoshkevich
On Wed, Nov 11, 2026 at 07:29:44PM +0100, Gerald Schaefer wrote:
> +#if IS_ENABLED(CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION)
> +bool arch_hugetlb_migration_supported(struct hstate *h)
> +{
Oh, would you agree to such one? ;)
return IS_ENABLED(CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION) &&
__hugetlb_valid_size(huge_page_size(h));
> + return __hugetlb_valid_size(huge_page_size(h));
> +}
> +#endif
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2] s390/mm: Allow hugepage migration for s390
2026-11-11 19:14 ` sashiko-bot
@ 2026-11-12 11:13 ` Gerald Schaefer
0 siblings, 0 replies; 4+ messages in thread
From: Gerald Schaefer @ 2026-11-12 11:13 UTC (permalink / raw)
To: Claudio Imbrenda
Cc: sashiko-reviews, linux-s390, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger
On Wed, 11 Nov 2026 19:14:22 +0000
sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 2 potential
> issues to consider:
> - [High] s390/mm: guest storage key loss on 1M/2G hugetlbfs page
> migration
@Claudio, could you please have a look, if this is a valid issue?
> - [Medium] s390/mm: loss of soft-dirty bit in __pte_to_rste() and
> __rste_to_pte() on hugetlb migration
No problem, soft-dirty tracking not supported for hugetlbfs, see below.
> --
>
> commit d03e5331e4e0b88aa75246fc7dc6aef18e7c8cdd
> Author: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
>
> s390/mm: Allow hugepage migration for s390
>
> This commit selects ARCH_ENABLE_HUGEPAGE_MIGRATION on s390 and defines
> arch_hugetlb_migration_supported() for 1M and 2G hugepages so hugetlbfs
> pages can be migrated and allocated from ZONE_MOVABLE.
>
> > diff --git a/arch/s390/mm/hugetlbpage.c b/arch/s390/mm/hugetlbpage.c
> > index f84aa9265430f..2c6e94888bd06 100644
> > --- a/arch/s390/mm/hugetlbpage.c
> > +++ b/arch/s390/mm/hugetlbpage.c
> > @@ -224,7 +224,7 @@ pte_t *huge_pte_offset(struct mm_struct *mm,
> > return (pte_t *) pmdp;
> > }
> >
> > -bool __init arch_hugetlb_valid_size(unsigned long size)
> > +static bool __hugetlb_valid_size(unsigned long size)
> > {
> > if (cpu_has_edat1() && size == PMD_SIZE)
> > return true;
> > @@ -241,3 +241,15 @@ unsigned int __init arch_hugetlb_cma_order(void)
> >
> > return 0;
> > }
> > +
> > +bool __init arch_hugetlb_valid_size(unsigned long size)
> > +{
> > + return __hugetlb_valid_size(size);
> > +}
> > +
> > +#if IS_ENABLED(CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION)
> > +bool arch_hugetlb_migration_supported(struct hstate *h)
> > +{
> > + return __hugetlb_valid_size(huge_page_size(h));
> > +}
> > +#endif
>
> [Severity: High]
> Does migrating a 1M or 2G hugetlbfs folio backing a KVM guest lose the
> guest's hardware storage keys?
>
> For 1M and 2G mappings (KVM_CAP_S390_HPAGE_1M / KVM_CAP_S390_HPAGE_2G),
> the KVM gmap uses large leaf CRSTEs without PGSTEs, and guest storage keys
> live only in the physical page frames. When unmap_and_move_hugetlb_folio()
> unmaps the folio via mmu_notifier_invalidate_range_start(),
> _gmap_unmap_crste() clears the large CRSTE to _CRSTE_EMPTY without saving
> or splitting the hardware storage keys:
>
> arch/s390/kvm/gmap/gmap.c:_gmap_unmap_crste() {
> ...
> if (!old.h.fc)
> return 0;
>
> if (old.s.fc1.pr && test_bit(GMAP_FLAG_EXPORT_ON_UNMAP, &priv->gmap->flags))
> folio = phys_to_folio(crste_origin_large(old));
> ok = gmap_crstep_xchg_atomic(priv->gmap, crstep, old, _CRSTE_EMPTY(old.h.tt), gfn);
> ...
> }
>
> folio_copy() -> copy_highpage() -> copy_page() then copies only the 4K
> page contents via mvcl and does not copy the hardware storage keys to the
> destination frames, leaving the guest with stale storage keys and causing
> guest protection exceptions or memory corruption.
>
> [Severity: Medium]
> Does migrating a hugetlbfs page also drop its soft-dirty bit in
> __pte_to_rste() and __rste_to_pte()?
>
> When try_to_migrate_one() installs a hugetlb migration entry, it sets
> _PAGE_SOFT_DIRTY via pte_swp_mksoft_dirty() and calls set_huge_pte_at().
> However, the swap entry branches in __pte_to_rste() and __rste_to_pte() do
> not transfer _PAGE_SOFT_DIRTY to and from _SEGMENT_ENTRY_SOFT_DIRTY:
>
> arch/s390/mm/hugetlbpage.c:__pte_to_rste() {
> ...
> } else if (!pte_none(pte)) {
> /* swap pte */
> arch_entry = __pte_to_swp_entry(pte);
> rste = mk_swap_rste(__swp_type(arch_entry), __swp_offset(arch_entry));
> ...
> }
>
> arch/s390/mm/hugetlbpage.c:__rste_to_pte() {
> ...
> } else if (!none) {
> /* swap rste */
> arch_entry = __rste_to_swp_entry(rste);
> pte = mk_swap_pte(__swp_type_rste(arch_entry), __swp_offset_rste(arch_entry));
> pteval = pte_val(pte);
> ...
> }
>
> As a result, remove_migration_pte() reads back old_pte via huge_ptep_get()
> with pte_swp_soft_dirty(old_pte) == 0 and clears _PAGE_SOFT_DIRTY on the
> restored hugepage PTE, breaking soft-dirty tracking via /proc/pid/pagemap.
Hugetlbfs does not support soft-dirty page tracking in the kernel:
vma_wants_writenotify() in mm/vma.c explicitly excludes hugetlb VMAs from
soft-dirty tracking, clear_refs_walk_ops in fs/proc/task_mmu.c does not
implement a hugetlb_entry callback, and mm/hugetlb.c never sets or
preserves soft-dirty bits on hugetlb PTEs or migration entries.
The RSTE swap entry soft-dirty bit (bit 62) exists for THP PMD
swap/migration entries rather than hugetlbfs. Generic hugetlb migration
handling in mm/hugetlb.c (copy_hugetlb_page_range() and
hugetlb_change_protection()) also does not preserve pte_swp_soft_dirty()
when rebuilding hugetlb migration swap entries.
However, I was not aware that try_to_migrate_one() actually does set
_PAGE_SOFT_DIRTY via pte_swp_mksoft_dirty() also for hugetlbfs pages,
even though it is not being used anywhere yet. This bit is indeed lost
after __pte_to_rste() conversion from a swap PTE. But it does not break
soft-dirty tracking for hugetlbfs, because that does not exist. It also
does not conflict with or corrupt the RSTE swap type or offset calculation.
Of course, it probably would be good practice to already preserve
_PAGE_SOFT_DIRTY now, even if it is not needed yet, and further changes to
generic code would be required if it should ever be supported. Will look
into this in v3.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-11-12 11:13 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-11 18:29 [PATCH v2] s390/mm: Allow hugepage migration for s390 Gerald Schaefer
2026-11-11 19:14 ` sashiko-bot
2026-11-12 11:13 ` Gerald Schaefer
2026-11-12 7:54 ` Alexander Gordeev
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox