From 123b7c7c2ba725daf3bfa5ce421d65b92cb5c075 Mon Sep 17 00:00:00 2001 From: Harald Freudenberger Date: Wed, 23 Jul 2025 15:39:12 +0200 Subject: [PATCH 1/7] s390/ap: Unmask SLCF bit in card and queue ap functions sysfs The SLCF bit ("stateless command filtering") introduced with CEX8 cards was because of the function mask's default value suppressed when user space read the ap function for an AP card or queue. Unmask this bit so that user space applications like lszcrypt can evaluate and list this feature. Fixes: d4c53ae8e494 ("s390/ap: store TAPQ hwinfo in struct ap_card") Signed-off-by: Harald Freudenberger Reviewed-by: Holger Dengler Signed-off-by: Heiko Carstens Signed-off-by: Alexander Gordeev --- arch/s390/include/asm/ap.h | 2 +- drivers/s390/crypto/ap_bus.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/s390/include/asm/ap.h b/arch/s390/include/asm/ap.h index 395b02d6a133..352108727d7e 100644 --- a/arch/s390/include/asm/ap.h +++ b/arch/s390/include/asm/ap.h @@ -103,7 +103,7 @@ struct ap_tapq_hwinfo { unsigned int accel : 1; /* A */ unsigned int ep11 : 1; /* X */ unsigned int apxa : 1; /* APXA */ - unsigned int : 1; + unsigned int slcf : 1; /* Cmd filtering avail. */ unsigned int class : 8; unsigned int bs : 2; /* SE bind/assoc */ unsigned int : 14; diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h index 88b625ba1978..4b7ffa840563 100644 --- a/drivers/s390/crypto/ap_bus.h +++ b/drivers/s390/crypto/ap_bus.h @@ -180,7 +180,7 @@ struct ap_card { atomic64_t total_request_count; /* # requests ever for this AP device.*/ }; -#define TAPQ_CARD_HWINFO_MASK 0xFEFF0000FFFF0F0FUL +#define TAPQ_CARD_HWINFO_MASK 0xFFFF0000FFFF0F0FUL #define ASSOC_IDX_INVALID 0x10000 #define to_ap_card(x) container_of((x), struct ap_card, ap_dev.device) From 56f4cfab1c93b14da422cdcd23898eb008033696 Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Tue, 29 Jul 2025 14:24:36 +0200 Subject: [PATCH 2/7] s390/mm: Set high_memory at the end of the identity mapping The value of high_memory variable is set by set_high_memory() function to a value returned by memblock_end_of_DRAM(). The latter function returns by default the upper bound of the last online memory block, not the upper bound of the directly mapped memory region. As result, in case the end of memory happens to be offline, high_memory variable is set to a value that is short on the last offline memory blocks size: RANGE SIZE STATE REMOVABLE BLOCK 0x0000000000000000-0x000000ffffffffff 1T online yes 0-511 0x0000010000000000-0x0000011fffffffff 128G offline 512-575 Memory block size: 2G Total online memory: 1T Total offline memory: 128G crash> p/x vm_layout $1 = { kaslr_offset = 0x3453e918000, kaslr_offset_phys = 0xa534218000, identity_base = 0x0, identity_size = 0x12000000000 } crash> p/x high_memory $2 = 0x10000000000 In the past the value of high_memory was derived from max_low_pfn, which in turn was derived from the identity_size. Since identity_size accommodates the whole memory size - including tailing offline blocks, the offlined blocks did not impose any problem. But since commit e120d1bc12da ("arch, mm: set high_memory in free_area_init()") the value of high_memory is derived from the last memblock online region, and that is where the problem comes from. The value of high_memory is used by several drivers and by external tools (e.g. crash tool aborts while loading a dump). Similarily to ARM, use the override path provided by set_high_memory() function and set the value of high_memory at the end of the identity mapping early. That forces set_high_memory() to leave in high_memory the correct value, even when the end of available memory is offline. Fixes: e120d1bc12da ("arch, mm: set high_memory in free_area_init()") Tested-by: Mikhail Zaslonko Reviewed-by: Heiko Carstens Reviewed-by: Gerald Schaefer Signed-off-by: Alexander Gordeev --- arch/s390/kernel/setup.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index f244c5560e7f..5c9789804120 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -719,6 +719,11 @@ static void __init memblock_add_physmem_info(void) memblock_set_node(0, ULONG_MAX, &memblock.memory, 0); } +static void __init setup_high_memory(void) +{ + high_memory = __va(ident_map_size); +} + /* * Reserve memory used for lowcore. */ @@ -951,6 +956,7 @@ void __init setup_arch(char **cmdline_p) free_physmem_info(); setup_memory_end(); + setup_high_memory(); memblock_dump_all(); setup_memory(); From ccb0aa03d046ff84492396d2e90b408fa5b24a00 Mon Sep 17 00:00:00 2001 From: Steffen Maier Date: Thu, 10 Jul 2025 17:05:22 +0200 Subject: [PATCH 3/7] s390: Support CONFIG_TRACE_MMIO_ACCESS Enable the functionality of commits d593d64f043a ("lib: Add register read/write tracing support") 210031971cdd ("asm-generic/io: Add logging support for MMIO accessors"). It only depends on explicit function calls for the tracing. Signed-off-by: Steffen Maier Reviewed-by: Niklas Schnelle Signed-off-by: Heiko Carstens Signed-off-by: Alexander Gordeev --- arch/s390/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 25a773e6596e..ac162e62da86 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -102,6 +102,7 @@ config S390 select ARCH_HAS_UBSAN select ARCH_HAS_VDSO_TIME_DATA select ARCH_HAVE_NMI_SAFE_CMPXCHG + select ARCH_HAVE_TRACE_MMIO_ACCESS select ARCH_INLINE_READ_LOCK select ARCH_INLINE_READ_LOCK_BH select ARCH_INLINE_READ_LOCK_IRQ From 10dd5a0009898ba35eafeb6087e5c83b84742ff1 Mon Sep 17 00:00:00 2001 From: Gerald Schaefer Date: Tue, 29 Jul 2025 13:16:19 +0200 Subject: [PATCH 4/7] s390/mm: Enable THP_SWAP and THP_MIGRATION After hugetlbfs PTE_MARKER support for s390 introduced region-third and segment table swap entries, it is now possible to also enable THP_SWAP and THP_MIGRATION for s390. s390 has different layout for PTE and region / segment table entries (RSTE). This is also true for swap entries, and their swap type and offset encoding. For hugetlbfs PTE_MARKER support, s390 has internal __swp_type_rste() and __swp_offset_rste() helpers to correctly handle RSTE swap entries. But common swap code does not know about this difference, and only uses __swp_type(), __swp_offset() and __swp_entry() helpers for conversion between arch-dependent and arch-independent representation of swp_entry_t for all pagetable levels. On s390, those helpers only work for PTE swap entries. Therefore, implement __pmd_to_swp_entry() to build a fake PTE swap entry and return the arch-dependent representation of that. Correspondingly, implement __swp_entry_to_pmd() to convert that into a proper PMD swap entry again. With this, the arch-dependent swp_entry_t representation will always look like a PTE swap entry in common code. This is somewhat similar to fake PTEs in hugetlbfs code for s390, but only requires conversion of the swap type and offset, and not all the possible PTE bits. For PMD swap entry SOFT_DIRTY handling, use the same helpers as for normal PMDs. Similar to PTEs, the SOFT_DIRTY bit location is the same for swap and normal entries. Reviewed-by: Heiko Carstens Signed-off-by: Gerald Schaefer Signed-off-by: Alexander Gordeev --- arch/s390/Kconfig | 2 ++ arch/s390/include/asm/pgtable.h | 45 +++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index ac162e62da86..f41f604f0297 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -74,6 +74,7 @@ config S390 select ARCH_ENABLE_MEMORY_HOTPLUG if SPARSEMEM select ARCH_ENABLE_MEMORY_HOTREMOVE select ARCH_ENABLE_SPLIT_PMD_PTLOCK if PGTABLE_LEVELS > 2 + select ARCH_ENABLE_THP_MIGRATION if TRANSPARENT_HUGEPAGE select ARCH_HAS_CPU_FINALIZE_INIT select ARCH_HAS_CURRENT_STACK_POINTER select ARCH_HAS_DEBUG_VIRTUAL @@ -150,6 +151,7 @@ config S390 select ARCH_WANT_KERNEL_PMD_MKWRITE select ARCH_WANT_LD_ORPHAN_WARN select ARCH_WANT_OPTIMIZE_HUGETLB_VMEMMAP + select ARCH_WANTS_THP_SWAP select BUILDTIME_TABLE_SORT select CLONE_BACKWARDS2 select DCACHE_WORD_ACCESS if !KMSAN diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 6d8bc27a366e..c1a7a92f0575 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -963,6 +963,12 @@ static inline pmd_t pmd_clear_soft_dirty(pmd_t pmd) return clear_pmd_bit(pmd, __pgprot(_SEGMENT_ENTRY_SOFT_DIRTY)); } +#ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION +#define pmd_swp_soft_dirty(pmd) pmd_soft_dirty(pmd) +#define pmd_swp_mksoft_dirty(pmd) pmd_mksoft_dirty(pmd) +#define pmd_swp_clear_soft_dirty(pmd) pmd_clear_soft_dirty(pmd) +#endif + /* * query functions pte_write/pte_dirty/pte_young only work if * pte_present() is true. Undefined behaviour if not.. @@ -1979,6 +1985,45 @@ static inline unsigned long __swp_offset_rste(swp_entry_t entry) #define __rste_to_swp_entry(rste) ((swp_entry_t) { rste }) +/* + * s390 has different layout for PTE and region / segment table entries (RSTE). + * This is also true for swap entries, and their swap type and offset encoding. + * For hugetlbfs PTE_MARKER support, s390 has internal __swp_type_rste() and + * __swp_offset_rste() helpers to correctly handle RSTE swap entries. + * + * But common swap code does not know about this difference, and only uses + * __swp_type(), __swp_offset() and __swp_entry() helpers for conversion between + * arch-dependent and arch-independent representation of swp_entry_t for all + * pagetable levels. On s390, those helpers only work for PTE swap entries. + * + * Therefore, implement __pmd_to_swp_entry() to build a fake PTE swap entry + * and return the arch-dependent representation of that. Correspondingly, + * implement __swp_entry_to_pmd() to convert that into a proper PMD swap + * entry again. With this, the arch-dependent swp_entry_t representation will + * always look like a PTE swap entry in common code. + * + * This is somewhat similar to fake PTEs in hugetlbfs code for s390, but only + * requires conversion of the swap type and offset, and not all the possible + * PTE bits. + */ +static inline swp_entry_t __pmd_to_swp_entry(pmd_t pmd) +{ + swp_entry_t arch_entry; + pte_t pte; + + arch_entry = __rste_to_swp_entry(pmd_val(pmd)); + pte = mk_swap_pte(__swp_type_rste(arch_entry), __swp_offset_rste(arch_entry)); + return __pte_to_swp_entry(pte); +} + +static inline pmd_t __swp_entry_to_pmd(swp_entry_t arch_entry) +{ + pmd_t pmd; + + pmd = __pmd(mk_swap_rste(__swp_type(arch_entry), __swp_offset(arch_entry))); + return pmd; +} + extern int vmem_add_mapping(unsigned long start, unsigned long size); extern void vmem_remove_mapping(unsigned long start, unsigned long size); extern int __vmem_map_4k_page(unsigned long addr, unsigned long phys, pgprot_t prot, bool alloc); From daa8af80d283ee9a7d42dd6f164a65036665b9d4 Mon Sep 17 00:00:00 2001 From: Sumanth Korikkar Date: Mon, 4 Aug 2025 11:57:03 +0200 Subject: [PATCH 5/7] s390/mm: Allocate page table with PAGE_SIZE granularity Make vmem_pte_alloc() consistent by always allocating page table of PAGE_SIZE granularity, regardless of whether page_table_alloc() (with slab) or memblock_alloc() is used. This ensures page table can be fully freed when the corresponding page table entries are removed. Fixes: d08d4e7cd6bf ("s390/mm: use full 4KB page for 2KB PTE") Reviewed-by: Heiko Carstens Reviewed-by: Alexander Gordeev Signed-off-by: Sumanth Korikkar Signed-off-by: Alexander Gordeev --- arch/s390/mm/vmem.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c index 448dd6ed1069..f48ef361bc83 100644 --- a/arch/s390/mm/vmem.c +++ b/arch/s390/mm/vmem.c @@ -64,13 +64,12 @@ void *vmem_crst_alloc(unsigned long val) pte_t __ref *vmem_pte_alloc(void) { - unsigned long size = PTRS_PER_PTE * sizeof(pte_t); pte_t *pte; if (slab_is_available()) - pte = (pte_t *) page_table_alloc(&init_mm); + pte = (pte_t *)page_table_alloc(&init_mm); else - pte = (pte_t *) memblock_alloc(size, size); + pte = (pte_t *)memblock_alloc(PAGE_SIZE, PAGE_SIZE); if (!pte) return NULL; memset64((u64 *)pte, _PAGE_INVALID, PTRS_PER_PTE); From e29409faec87ffd2de2ed20b6109f303f129281b Mon Sep 17 00:00:00 2001 From: Mikhail Zaslonko Date: Tue, 5 Aug 2025 10:41:33 +0200 Subject: [PATCH 6/7] s390/boot: Fix startup debugging log Fix 'kernel image' end address for kaslr case. Fixes: ec6f9f7e5bbf ("s390/boot: Add startup debugging support") Reviewed-by: Alexander Gordeev Signed-off-by: Mikhail Zaslonko Signed-off-by: Heiko Carstens Signed-off-by: Alexander Gordeev --- arch/s390/boot/startup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c index 305e6c791071..93684a775716 100644 --- a/arch/s390/boot/startup.c +++ b/arch/s390/boot/startup.c @@ -384,7 +384,7 @@ static unsigned long setup_kernel_memory_layout(unsigned long kernel_size) kernel_start = round_down(kernel_end - kernel_size, THREAD_SIZE); boot_debug("Randomization range: 0x%016lx-0x%016lx\n", vmax - kaslr_len, vmax); boot_debug("kernel image: 0x%016lx-0x%016lx (kaslr)\n", kernel_start, - kernel_size + kernel_size); + kernel_start + kernel_size); } else if (vmax < __NO_KASLR_END_KERNEL || vsize > __NO_KASLR_END_KERNEL) { kernel_start = round_down(vmax - kernel_size, THREAD_SIZE); boot_debug("kernel image: 0x%016lx-0x%016lx (constrained)\n", kernel_start, From 2baf16f381decee303da406ca5a0991134260270 Mon Sep 17 00:00:00 2001 From: Tigran Mkrtchyan Date: Mon, 4 Aug 2025 11:33:21 +0200 Subject: [PATCH 7/7] s390/debug: Fix typo in debug_sprintf_format_fn() comment Signed-off-by: Tigran Mkrtchyan Link: https://lore.kernel.org/r/20250804093321.434674-1-tigran.mkrtchyan@desy.de Signed-off-by: Alexander Gordeev --- arch/s390/kernel/debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c index 2a41be2f7925..c62100dc62c8 100644 --- a/arch/s390/kernel/debug.c +++ b/arch/s390/kernel/debug.c @@ -1677,7 +1677,7 @@ EXPORT_SYMBOL(debug_dflt_header_fn); /* * prints debug data sprintf-formatted: - * debug_sprinf_event/exception calls must be used together with this view + * debug_sprintf_event/exception calls must be used together with this view */ #define DEBUG_SPRINTF_MAX_ARGS 10