From 8e9205d2a58989aff46000ef47021633146ca493 Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Sun, 11 Dec 2022 08:18:57 +0100 Subject: [PATCH] s390/mm: allocate Real Memory Copy Area in decompressor Move Real Memory Copy Area allocation to the decompressor. As result, memcpy_real() and memcpy_real_iter() movers become usable since the very moment the kernel starts. Reviewed-by: Heiko Carstens Signed-off-by: Alexander Gordeev Signed-off-by: Heiko Carstens --- arch/s390/boot/startup.c | 2 ++ arch/s390/boot/vmem.c | 15 +++++++++++++++ arch/s390/include/asm/maccess.h | 2 +- arch/s390/kernel/setup.c | 2 +- arch/s390/mm/maccess.c | 9 +-------- 5 files changed, 20 insertions(+), 10 deletions(-) diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c index c5d59df..cb4b743 100644 --- a/arch/s390/boot/startup.c +++ b/arch/s390/boot/startup.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -19,6 +20,7 @@ unsigned long __bootdata_preserved(__kaslr_offset); unsigned long __bootdata_preserved(__abs_lowcore); unsigned long __bootdata_preserved(__memcpy_real_area); +pte_t *__bootdata_preserved(memcpy_real_ptep); unsigned long __bootdata(__amode31_base); unsigned long __bootdata_preserved(VMALLOC_START); unsigned long __bootdata_preserved(VMALLOC_END); diff --git a/arch/s390/boot/vmem.c b/arch/s390/boot/vmem.c index af9124c..41ff38a 100644 --- a/arch/s390/boot/vmem.c +++ b/arch/s390/boot/vmem.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "decompressor.h" #include "boot.h" @@ -12,12 +13,21 @@ #define swapper_pg_dir vmlinux.swapper_pg_dir_off #define invalid_pg_dir vmlinux.invalid_pg_dir_off +/* + * Mimic virt_to_kpte() in lack of init_mm symbol. Skip pmd NULL check though. + */ +static inline pte_t *__virt_to_kpte(unsigned long va) +{ + return pte_offset_kernel(pmd_offset(pud_offset(p4d_offset(pgd_offset_k(va), va), va), va), va); +} + unsigned long __bootdata_preserved(s390_invalid_asce); unsigned long __bootdata(pgalloc_pos); unsigned long __bootdata(pgalloc_end); unsigned long __bootdata(pgalloc_low); enum populate_mode { + POPULATE_NONE, POPULATE_ONE2ONE, }; @@ -88,6 +98,8 @@ static pte_t *boot_pte_alloc(void) static unsigned long _pa(unsigned long addr, enum populate_mode mode) { switch (mode) { + case POPULATE_NONE: + return -1; case POPULATE_ONE2ONE: return addr; default: @@ -259,6 +271,9 @@ void setup_vmem(unsigned long online_end, unsigned long asce_limit) pgtable_populate_begin(online_end); pgtable_populate(0, sizeof(struct lowcore), POPULATE_ONE2ONE); pgtable_populate(0, online_end, POPULATE_ONE2ONE); + pgtable_populate(__memcpy_real_area, __memcpy_real_area + PAGE_SIZE, + POPULATE_NONE); + memcpy_real_ptep = __virt_to_kpte(__memcpy_real_area); pgtable_populate_end(); S390_lowcore.kernel_asce = swapper_pg_dir | asce_bits; diff --git a/arch/s390/include/asm/maccess.h b/arch/s390/include/asm/maccess.h index c7fa838..cfec314 100644 --- a/arch/s390/include/asm/maccess.h +++ b/arch/s390/include/asm/maccess.h @@ -7,7 +7,7 @@ struct iov_iter; extern unsigned long __memcpy_real_area; -void memcpy_real_init(void); +extern pte_t *memcpy_real_ptep; size_t memcpy_real_iter(struct iov_iter *iter, unsigned long src, size_t count); int memcpy_real(void *dest, unsigned long src, size_t count); #ifdef CONFIG_CRASH_DUMP diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 1ffaa85..9ae2f6b 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -1046,7 +1046,7 @@ void __init setup_arch(char **cmdline_p) * Create kernel page tables. */ paging_init(); - memcpy_real_init(); + /* * After paging_init created the kernel page table, the new PSWs * in lowcore can now run with DAT enabled. diff --git a/arch/s390/mm/maccess.c b/arch/s390/mm/maccess.c index a6314e2..7c66b3a 100644 --- a/arch/s390/mm/maccess.c +++ b/arch/s390/mm/maccess.c @@ -21,7 +21,7 @@ #include unsigned long __bootdata_preserved(__memcpy_real_area); -static __ro_after_init pte_t *memcpy_real_ptep; +pte_t *__bootdata_preserved(memcpy_real_ptep); static DEFINE_MUTEX(memcpy_real_mutex); static notrace long s390_kernel_write_odd(void *dst, const void *src, size_t size) @@ -79,13 +79,6 @@ notrace void *s390_kernel_write(void *dst, const void *src, size_t size) return dst; } -void __init memcpy_real_init(void) -{ - memcpy_real_ptep = vmem_get_alloc_pte(__memcpy_real_area, true); - if (!memcpy_real_ptep) - panic("Couldn't setup memcpy real area"); -} - size_t memcpy_real_iter(struct iov_iter *iter, unsigned long src, size_t count) { size_t len, copied, res = 0; -- 2.7.4