[PATCH 2/2] s390x: uncouple virtual and physical address spaces
Alexander Gordeev
agordeev at linux.ibm.com
Wed Nov 29 04:50:12 PST 2023
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 at 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
More information about the kexec
mailing list