Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <hca@linux.ibm.com>
Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>

authored by

Alexander Gordeev and committed by
Heiko Carstens
8e9205d2 e0e0a87b

+20 -10
+2
arch/s390/boot/startup.c
··· 3 3 #include <linux/elf.h> 4 4 #include <asm/boot_data.h> 5 5 #include <asm/sections.h> 6 + #include <asm/maccess.h> 6 7 #include <asm/cpu_mf.h> 7 8 #include <asm/setup.h> 8 9 #include <asm/kasan.h> ··· 20 19 unsigned long __bootdata_preserved(__kaslr_offset); 21 20 unsigned long __bootdata_preserved(__abs_lowcore); 22 21 unsigned long __bootdata_preserved(__memcpy_real_area); 22 + pte_t *__bootdata_preserved(memcpy_real_ptep); 23 23 unsigned long __bootdata(__amode31_base); 24 24 unsigned long __bootdata_preserved(VMALLOC_START); 25 25 unsigned long __bootdata_preserved(VMALLOC_END);
+15
arch/s390/boot/vmem.c
··· 5 5 #include <asm/facility.h> 6 6 #include <asm/sections.h> 7 7 #include <asm/mem_detect.h> 8 + #include <asm/maccess.h> 8 9 #include "decompressor.h" 9 10 #include "boot.h" 10 11 ··· 13 12 #define swapper_pg_dir vmlinux.swapper_pg_dir_off 14 13 #define invalid_pg_dir vmlinux.invalid_pg_dir_off 15 14 15 + /* 16 + * Mimic virt_to_kpte() in lack of init_mm symbol. Skip pmd NULL check though. 17 + */ 18 + static inline pte_t *__virt_to_kpte(unsigned long va) 19 + { 20 + return pte_offset_kernel(pmd_offset(pud_offset(p4d_offset(pgd_offset_k(va), va), va), va), va); 21 + } 22 + 16 23 unsigned long __bootdata_preserved(s390_invalid_asce); 17 24 unsigned long __bootdata(pgalloc_pos); 18 25 unsigned long __bootdata(pgalloc_end); 19 26 unsigned long __bootdata(pgalloc_low); 20 27 21 28 enum populate_mode { 29 + POPULATE_NONE, 22 30 POPULATE_ONE2ONE, 23 31 }; 24 32 ··· 98 88 static unsigned long _pa(unsigned long addr, enum populate_mode mode) 99 89 { 100 90 switch (mode) { 91 + case POPULATE_NONE: 92 + return -1; 101 93 case POPULATE_ONE2ONE: 102 94 return addr; 103 95 default: ··· 271 259 pgtable_populate_begin(online_end); 272 260 pgtable_populate(0, sizeof(struct lowcore), POPULATE_ONE2ONE); 273 261 pgtable_populate(0, online_end, POPULATE_ONE2ONE); 262 + pgtable_populate(__memcpy_real_area, __memcpy_real_area + PAGE_SIZE, 263 + POPULATE_NONE); 264 + memcpy_real_ptep = __virt_to_kpte(__memcpy_real_area); 274 265 pgtable_populate_end(); 275 266 276 267 S390_lowcore.kernel_asce = swapper_pg_dir | asce_bits;
+1 -1
arch/s390/include/asm/maccess.h
··· 7 7 struct iov_iter; 8 8 9 9 extern unsigned long __memcpy_real_area; 10 - void memcpy_real_init(void); 10 + extern pte_t *memcpy_real_ptep; 11 11 size_t memcpy_real_iter(struct iov_iter *iter, unsigned long src, size_t count); 12 12 int memcpy_real(void *dest, unsigned long src, size_t count); 13 13 #ifdef CONFIG_CRASH_DUMP
+1 -1
arch/s390/kernel/setup.c
··· 1046 1046 * Create kernel page tables. 1047 1047 */ 1048 1048 paging_init(); 1049 - memcpy_real_init(); 1049 + 1050 1050 /* 1051 1051 * After paging_init created the kernel page table, the new PSWs 1052 1052 * in lowcore can now run with DAT enabled.
+1 -8
arch/s390/mm/maccess.c
··· 21 21 #include <asm/maccess.h> 22 22 23 23 unsigned long __bootdata_preserved(__memcpy_real_area); 24 - static __ro_after_init pte_t *memcpy_real_ptep; 24 + pte_t *__bootdata_preserved(memcpy_real_ptep); 25 25 static DEFINE_MUTEX(memcpy_real_mutex); 26 26 27 27 static notrace long s390_kernel_write_odd(void *dst, const void *src, size_t size) ··· 77 77 spin_unlock_irqrestore(&s390_kernel_write_lock, flags); 78 78 79 79 return dst; 80 - } 81 - 82 - void __init memcpy_real_init(void) 83 - { 84 - memcpy_real_ptep = vmem_get_alloc_pte(__memcpy_real_area, true); 85 - if (!memcpy_real_ptep) 86 - panic("Couldn't setup memcpy real area"); 87 80 } 88 81 89 82 size_t memcpy_real_iter(struct iov_iter *iter, unsigned long src, size_t count)