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 <agordeev@xxxxxxxxxxxxx> --- 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@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/kexec