summaryrefslogtreecommitdiff
path: root/arch/s390/boot
diff options
context:
space:
mode:
authorAlexander Gordeev <agordeev@linux.ibm.com>2022-12-11 08:18:57 +0100
committerHeiko Carstens <hca@linux.ibm.com>2023-01-13 14:15:06 +0100
commit8e9205d2a58989aff46000ef47021633146ca493 (patch)
tree8e3bbfa1a53d106fec806f8c85412133b47a0f9d /arch/s390/boot
parente0e0a87b4b85ac3bbf76327fc030e6134b657068 (diff)
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>
Diffstat (limited to 'arch/s390/boot')
-rw-r--r--arch/s390/boot/startup.c2
-rw-r--r--arch/s390/boot/vmem.c15
2 files changed, 17 insertions, 0 deletions
diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c
index c5d59df9fa62..cb4b743a5e17 100644
--- a/arch/s390/boot/startup.c
+++ b/arch/s390/boot/startup.c
@@ -3,6 +3,7 @@
#include <linux/elf.h>
#include <asm/boot_data.h>
#include <asm/sections.h>
+#include <asm/maccess.h>
#include <asm/cpu_mf.h>
#include <asm/setup.h>
#include <asm/kasan.h>
@@ -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 af9124c8c19c..41ff38a0e2dd 100644
--- a/arch/s390/boot/vmem.c
+++ b/arch/s390/boot/vmem.c
@@ -5,6 +5,7 @@
#include <asm/facility.h>
#include <asm/sections.h>
#include <asm/mem_detect.h>
+#include <asm/maccess.h>
#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;