Commit 8e9205d2 authored by Alexander Gordeev's avatar Alexander Gordeev Committed by Heiko Carstens

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: default avatarHeiko Carstens <hca@linux.ibm.com>
Signed-off-by: default avatarAlexander Gordeev <agordeev@linux.ibm.com>
Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
parent e0e0a87b
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include <linux/elf.h> #include <linux/elf.h>
#include <asm/boot_data.h> #include <asm/boot_data.h>
#include <asm/sections.h> #include <asm/sections.h>
#include <asm/maccess.h>
#include <asm/cpu_mf.h> #include <asm/cpu_mf.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/kasan.h> #include <asm/kasan.h>
...@@ -19,6 +20,7 @@ ...@@ -19,6 +20,7 @@
unsigned long __bootdata_preserved(__kaslr_offset); unsigned long __bootdata_preserved(__kaslr_offset);
unsigned long __bootdata_preserved(__abs_lowcore); unsigned long __bootdata_preserved(__abs_lowcore);
unsigned long __bootdata_preserved(__memcpy_real_area); unsigned long __bootdata_preserved(__memcpy_real_area);
pte_t *__bootdata_preserved(memcpy_real_ptep);
unsigned long __bootdata(__amode31_base); unsigned long __bootdata(__amode31_base);
unsigned long __bootdata_preserved(VMALLOC_START); unsigned long __bootdata_preserved(VMALLOC_START);
unsigned long __bootdata_preserved(VMALLOC_END); unsigned long __bootdata_preserved(VMALLOC_END);
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <asm/facility.h> #include <asm/facility.h>
#include <asm/sections.h> #include <asm/sections.h>
#include <asm/mem_detect.h> #include <asm/mem_detect.h>
#include <asm/maccess.h>
#include "decompressor.h" #include "decompressor.h"
#include "boot.h" #include "boot.h"
...@@ -12,12 +13,21 @@ ...@@ -12,12 +13,21 @@
#define swapper_pg_dir vmlinux.swapper_pg_dir_off #define swapper_pg_dir vmlinux.swapper_pg_dir_off
#define invalid_pg_dir vmlinux.invalid_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_preserved(s390_invalid_asce);
unsigned long __bootdata(pgalloc_pos); unsigned long __bootdata(pgalloc_pos);
unsigned long __bootdata(pgalloc_end); unsigned long __bootdata(pgalloc_end);
unsigned long __bootdata(pgalloc_low); unsigned long __bootdata(pgalloc_low);
enum populate_mode { enum populate_mode {
POPULATE_NONE,
POPULATE_ONE2ONE, POPULATE_ONE2ONE,
}; };
...@@ -88,6 +98,8 @@ static pte_t *boot_pte_alloc(void) ...@@ -88,6 +98,8 @@ static pte_t *boot_pte_alloc(void)
static unsigned long _pa(unsigned long addr, enum populate_mode mode) static unsigned long _pa(unsigned long addr, enum populate_mode mode)
{ {
switch (mode) { switch (mode) {
case POPULATE_NONE:
return -1;
case POPULATE_ONE2ONE: case POPULATE_ONE2ONE:
return addr; return addr;
default: default:
...@@ -259,6 +271,9 @@ void setup_vmem(unsigned long online_end, unsigned long asce_limit) ...@@ -259,6 +271,9 @@ void setup_vmem(unsigned long online_end, unsigned long asce_limit)
pgtable_populate_begin(online_end); pgtable_populate_begin(online_end);
pgtable_populate(0, sizeof(struct lowcore), POPULATE_ONE2ONE); pgtable_populate(0, sizeof(struct lowcore), POPULATE_ONE2ONE);
pgtable_populate(0, online_end, 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(); pgtable_populate_end();
S390_lowcore.kernel_asce = swapper_pg_dir | asce_bits; S390_lowcore.kernel_asce = swapper_pg_dir | asce_bits;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
struct iov_iter; struct iov_iter;
extern unsigned long __memcpy_real_area; 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); 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); int memcpy_real(void *dest, unsigned long src, size_t count);
#ifdef CONFIG_CRASH_DUMP #ifdef CONFIG_CRASH_DUMP
......
...@@ -1046,7 +1046,7 @@ void __init setup_arch(char **cmdline_p) ...@@ -1046,7 +1046,7 @@ void __init setup_arch(char **cmdline_p)
* Create kernel page tables. * Create kernel page tables.
*/ */
paging_init(); paging_init();
memcpy_real_init();
/* /*
* After paging_init created the kernel page table, the new PSWs * After paging_init created the kernel page table, the new PSWs
* in lowcore can now run with DAT enabled. * in lowcore can now run with DAT enabled.
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
#include <asm/maccess.h> #include <asm/maccess.h>
unsigned long __bootdata_preserved(__memcpy_real_area); 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 DEFINE_MUTEX(memcpy_real_mutex);
static notrace long s390_kernel_write_odd(void *dst, const void *src, size_t size) 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) ...@@ -79,13 +79,6 @@ notrace void *s390_kernel_write(void *dst, const void *src, size_t size)
return dst; 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 memcpy_real_iter(struct iov_iter *iter, unsigned long src, size_t count)
{ {
size_t len, copied, res = 0; size_t len, copied, res = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment