Rework vaddr_to_paddr() and paddr_to_vaddr() macros to reflect
the future uncoupling of physical and virtual address spaces in
kernel. Existing versions are not affected.

Signed-off-by: Alexander Gordeev <agord...@linux.ibm.com>
---
 arch/s390x.c   | 134 ++++++++++++++++++++++++++++++++++++++++++++++++-
 makedumpfile.c |   2 +
 makedumpfile.h |  12 ++++-
 3 files changed, 145 insertions(+), 3 deletions(-)

diff --git a/arch/s390x.c b/arch/s390x.c
index a01f164..8ba2267 100644
--- a/arch/s390x.c
+++ b/arch/s390x.c
@@ -59,6 +59,69 @@
 #define rsg_offset(x, y)       (rsg_index( x, y) * sizeof(unsigned long))
 #define pte_offset(x)          (pte_index(x) * sizeof(unsigned long))
 
+#define LOWCORE_SIZE           0x2000
+
+#define OS_INFO_VERSION_MAJOR  1
+#define OS_INFO_VERSION_MINOR  1
+
+#define OS_INFO_VMCOREINFO     0
+#define OS_INFO_REIPL_BLOCK    1
+#define OS_INFO_FLAGS_ENTRY    2
+#define OS_INFO_RESERVED       3
+#define OS_INFO_IDENTITY_BASE  4
+#define OS_INFO_KASLR_OFFSET   5
+#define OS_INFO_KASLR_OFF_PHYS 6
+#define OS_INFO_VMEMMAP                7
+#define OS_INFO_AMODE31_START  8
+#define OS_INFO_AMODE31_END    9
+
+struct os_info_entry {
+       union {
+               __u64   addr;
+               __u64   val;
+       };
+       __u64   size;
+       __u32   csum;
+} __attribute__((packed));
+
+struct os_info {
+       __u64   magic;
+       __u32   csum;
+       __u16   version_major;
+       __u16   version_minor;
+       __u64   crashkernel_addr;
+       __u64   crashkernel_size;
+       struct  os_info_entry entry[10];
+       __u8    reserved[3864];
+} __attribute__((packed));
+
+#define S390X_LC_OS_INFO       0x0e18
+
+struct s390_ops {
+       unsigned long long      (*virt_to_phys)(unsigned long vaddr);
+       unsigned long           (*phys_to_virt)(unsigned long long paddr);
+};
+
+static unsigned long long vaddr_to_paddr_s390x_legacy(unsigned long vaddr);
+static unsigned long long vaddr_to_paddr_s390x_vr(unsigned long vaddr);
+static unsigned long paddr_to_vaddr_s390x_legacy(unsigned long long paddr);
+static unsigned long paddr_to_vaddr_s390x_vr(unsigned long long paddr);
+
+struct s390_ops s390_ops = {
+       .virt_to_phys = vaddr_to_paddr_s390x_legacy,
+       .phys_to_virt = paddr_to_vaddr_s390x_legacy,
+};
+
+unsigned long long vaddr_to_paddr_s390x(unsigned long vaddr)
+{
+       return s390_ops.virt_to_phys(vaddr);
+}
+
+unsigned long paddr_to_vaddr_s390x(unsigned long long paddr)
+{
+       return s390_ops.phys_to_virt(paddr);
+}
+
 int
 set_s390x_max_physmem_bits(void)
 {
@@ -88,12 +151,53 @@ set_s390x_max_physmem_bits(void)
        return FALSE;
 }
 
+static int s390x_init_vm(void)
+{
+       struct os_info os_info;
+       ulong addr;
+
+       if (!readmem(PADDR, S390X_LC_OS_INFO, &addr,
+                       sizeof(addr)) || !addr) {
+               ERRMSG("Can't get s390x os_info ptr.\n");
+               return FALSE;
+       }
+
+       if (addr == 0)
+               return TRUE;
+
+       if (!readmem(PADDR, addr, &os_info, offsetof(struct os_info, 
reserved))) {
+               ERRMSG("Can't get os_info header.\n");
+               return FALSE;
+       }
+
+       if (!os_info.entry[OS_INFO_KASLR_OFFSET].val)
+               return TRUE;
+
+       MSG("The -vr kernel detected.\n");
+
+       info->identity_map_base   = os_info.entry[OS_INFO_IDENTITY_BASE].val;
+       info->kvbase              = os_info.entry[OS_INFO_KASLR_OFFSET].val;
+       info->__kaslr_offset_phys = os_info.entry[OS_INFO_KASLR_OFF_PHYS].val;
+       info->vmemmap_start       = os_info.entry[OS_INFO_VMEMMAP].val;
+       info->amode31_start       = os_info.entry[OS_INFO_AMODE31_START].val;
+       info->amode31_end         = os_info.entry[OS_INFO_AMODE31_END].val;
+
+       s390_ops.virt_to_phys   = vaddr_to_paddr_s390x_vr;
+       s390_ops.phys_to_virt   = paddr_to_vaddr_s390x_vr;
+
+       return TRUE;
+}
+
+
 int
 get_machdep_info_s390x(void)
 {
        unsigned long vmalloc_start;
        char *term_str = getenv("TERM");
 
+       if (!s390x_init_vm())
+               return FALSE;
+
        if (term_str && strcmp(term_str, "dumb") == 0)
                /* '\r' control character is ignored on "dumb" terminal. */
                flag_ignore_r_char = 1;
@@ -295,8 +399,8 @@ vtop_s390x(unsigned long vaddr)
        return paddr;
 }
 
-unsigned long long
-vaddr_to_paddr_s390x(unsigned long vaddr)
+static unsigned long long
+vaddr_to_paddr_s390x_legacy(unsigned long vaddr)
 {
        unsigned long long paddr;
 
@@ -320,6 +424,32 @@ vaddr_to_paddr_s390x(unsigned long vaddr)
        return paddr;
 }
 
+static unsigned long long
+vaddr_to_paddr_s390x_vr(unsigned long vaddr)
+{
+       if (vaddr < LOWCORE_SIZE)
+               return vaddr;
+       if ((vaddr < info->amode31_end) && (vaddr >= info->amode31_start))
+               return vaddr;
+       if (vaddr < info->vmemmap_start)
+               return vaddr - info->identity_map_base;
+       if (vaddr >= info->kvbase)
+               return vaddr - info->kvbase + info->__kaslr_offset_phys;
+       return vtop_s390x(vaddr);
+}
+
+unsigned long
+paddr_to_vaddr_s390x_legacy(unsigned long long paddr)
+{
+       return (unsigned long)paddr_to_vaddr_general(paddr);
+}
+
+unsigned long
+paddr_to_vaddr_s390x_vr(unsigned long long paddr)
+{
+       return info->identity_map_base + (unsigned long)paddr;
+}
+
 struct addr_check {
        unsigned long addr;
        int found;
diff --git a/makedumpfile.c b/makedumpfile.c
index a6ec9d4..568889b 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -1654,6 +1654,7 @@ get_symbol_info(void)
        SYMBOL_INIT(max_pfn, "max_pfn");
        SYMBOL_INIT(modules, "modules");
        SYMBOL_INIT(high_memory, "high_memory");
+       SYMBOL_INIT(__kernel_base, "__kernel_base");
        SYMBOL_INIT(linux_banner, "linux_banner");
        SYMBOL_INIT(bios_cpu_apicid, "bios_cpu_apicid");
        SYMBOL_INIT(x86_bios_cpu_apicid, "x86_bios_cpu_apicid");
@@ -2819,6 +2820,7 @@ read_vmcoreinfo(void)
        READ_SYMBOL("log_next_idx", log_next_idx);
        READ_SYMBOL("max_pfn", max_pfn);
        READ_SYMBOL("high_memory", high_memory);
+       READ_SYMBOL("__kernel_base", __kernel_base);
        READ_SYMBOL("node_remap_start_vaddr", node_remap_start_vaddr);
        READ_SYMBOL("node_remap_end_vaddr", node_remap_end_vaddr);
        READ_SYMBOL("node_remap_start_pfn", node_remap_start_pfn);
diff --git a/makedumpfile.h b/makedumpfile.h
index 59a809c..81e2daf 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -1235,6 +1235,7 @@ unsigned long long vaddr_to_paddr_ppc(unsigned long 
vaddr);
 #ifdef __s390x__ /* s390x */
 int get_machdep_info_s390x(void);
 unsigned long long vaddr_to_paddr_s390x(unsigned long vaddr);
+unsigned long paddr_to_vaddr_s390x(unsigned long long paddr);
 int is_iomem_phys_addr_s390x(unsigned long addr);
 #define find_vmemmap()         stub_false()
 #define get_phys_base()                stub_true()
@@ -1242,7 +1243,7 @@ int is_iomem_phys_addr_s390x(unsigned long addr);
 #define get_versiondep_info()  stub_true()
 #define get_kaslr_offset(X)    get_kaslr_offset_general(X)
 #define vaddr_to_paddr(X)      vaddr_to_paddr_s390x(X)
-#define paddr_to_vaddr(X)      paddr_to_vaddr_general(X)
+#define paddr_to_vaddr(X)      paddr_to_vaddr_s390x(X)
 #define is_phys_addr(X)                is_iomem_phys_addr_s390x(X)
 #define arch_crashkernel_mem_size()    stub_false()
 #endif          /* s390x */
@@ -1760,6 +1761,14 @@ struct DumpInfo {
        pthread_mutex_t current_pfn_mutex;
        pthread_mutex_t page_data_mutex;
        pthread_mutex_t filter_mutex;
+
+#ifdef __s390x__ /* s390x */
+       unsigned long identity_map_base;
+       unsigned long kvbase;
+       unsigned long __kaslr_offset_phys;
+       unsigned long amode31_start;
+       unsigned long amode31_end;
+#endif
 };
 extern struct DumpInfo         *info;
 
@@ -1869,6 +1878,7 @@ struct symbol_table {
         * vmalloc_start address on s390x arch
         */
        unsigned long long      high_memory;
+       unsigned long long      __kernel_base;
 
        /*
         * for sadump
-- 
2.40.1


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

Reply via email to