[Crash-utility] [PATCH 3/3] s390x: uncouple physical and virtual memory spaces

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Rework VTOP and PTOV 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>
---
 defs.h  |  20 ++++-
 s390x.c | 231 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 247 insertions(+), 4 deletions(-)

diff --git a/defs.h b/defs.h
index 5218a94..20237b7 100644
--- a/defs.h
+++ b/defs.h
@@ -4564,9 +4564,9 @@ struct efi_memory_desc_t {
 #define _64BIT_
 #define MACHINE_TYPE       "S390X"
 
-#define PTOV(X)            ((unsigned long)(X)+(machdep->kvbase))
-#define VTOP(X)            ((unsigned long)(X)-(machdep->kvbase))
-#define IS_VMALLOC_ADDR(X) (vt->vmalloc_start && (ulong)(X) >= vt->vmalloc_start)
+#define PTOV(X)            s390x_PTOV((ulong)(X))
+#define VTOP(X)            s390x_VTOP((ulong)(X))
+#define IS_VMALLOC_ADDR(X) s390x_IS_VMALLOC_ADDR(X)
 #define PTRS_PER_PTE    512
 #define PTRS_PER_PMD    1024
 #define PTRS_PER_PGD    2048
@@ -6827,7 +6827,21 @@ void get_s390_panicmsg(char *);
  *  s390x.c
  */
 #ifdef S390X
+
+struct machine_specific
+{
+	ulong (*virt_to_phys)(ulong vaddr);
+	ulong (*phys_to_virt)(ulong paddr);
+	int (*is_vmalloc_addr)(ulong vaddr);
+	ulong __kaslr_offset_phys;
+	ulong amode31_start;
+	ulong amode31_end;
+};
+
 void s390x_init(int);
+ulong s390x_PTOV(ulong);
+ulong s390x_VTOP(ulong);
+int s390x_IS_VMALLOC_ADDR(ulong);
 void s390x_dump_machdep_table(ulong);
 #define display_idt_table() \
         error(FATAL, "-d option is not applicable to S390X architecture\n")
diff --git a/s390x.c b/s390x.c
index 4024d84..d8d7041 100644
--- a/s390x.c
+++ b/s390x.c
@@ -47,6 +47,7 @@
 #define S390X_PSW_MASK_PSTATE	0x0001000000000000UL
 
 #define S390X_LC_VMCORE_INFO	0xe0c
+#define S390X_LC_OS_INFO	0xe18
 
 /*
  * Flags for Region and Segment table entries.
@@ -168,6 +169,19 @@ static struct line_number_hook s390x_line_number_hooks[];
 static int s390x_is_uvaddr(ulong, struct task_context *);
 static int s390x_get_kvaddr_ranges(struct vaddr_range *);
 static int set_s390x_max_physmem_bits(void);
+static ulong s390x_generic_VTOP(ulong vaddr);
+static ulong s390x_generic_PTOV(ulong paddr);
+static int s390x_generic_IS_VMALLOC_ADDR(ulong vaddr);
+static ulong s390x_vr_VTOP(ulong vaddr);
+static ulong s390x_vr_PTOV(ulong paddr);
+static int s390x_vr_IS_VMALLOC_ADDR(ulong vaddr);
+static int s390x_vr_is_kvaddr(ulong);
+
+struct machine_specific s390x_machine_specific = {
+	.virt_to_phys = s390x_generic_VTOP,
+	.phys_to_virt = s390x_generic_PTOV,
+	.is_vmalloc_addr = s390x_generic_IS_VMALLOC_ADDR,
+};
 
 /*
  * struct lowcore name (old: "_lowcore", new: "lowcore")
@@ -546,6 +560,210 @@ static void s390x_check_kaslr(void)
 	free(vmcoreinfo);
 }
 
+#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));
+
+struct vm_info {
+	__u64 __identity_base;
+	__u64 __kaslr_offset;
+	__u64 __kaslr_offset_phys;
+	__u64 amode31_start;
+	__u64 amode31_end;
+};
+
+static bool
+vmcoreinfo_read_u64(const char *key, __u64 *val)
+{
+	char *string;
+
+	string = pc->read_vmcoreinfo(key);
+	if (string) {
+		*val = strtoul(string, NULL, 16);
+		free(string);
+		return true;
+	}
+
+	return false;
+}
+
+static bool vmcoreinfo_read_vm_info(struct vm_info *_vm_info)
+{
+	struct vm_info vm_info;
+
+	if (!vmcoreinfo_read_u64("IDENTITYBASE",  &vm_info.__identity_base) ||
+	    !vmcoreinfo_read_u64("KERNELOFFSET",  &vm_info.__kaslr_offset) ||
+	    !vmcoreinfo_read_u64("KERNELOFFPHYS", &vm_info.__kaslr_offset_phys) ||
+	    !vmcoreinfo_read_u64("SAMODE31",      &vm_info.amode31_start) ||
+	    !vmcoreinfo_read_u64("EAMODE31",      &vm_info.amode31_end))
+		return false;
+
+	*_vm_info = vm_info;
+
+	return true;
+}
+
+static bool os_info_read_vm_info(struct vm_info *vm_info)
+{
+	struct os_info os_info;
+	ulong addr;
+
+	if (!readmem(S390X_LC_OS_INFO, PHYSADDR, &addr,
+		    sizeof(addr), "s390x os_info ptr",
+		    QUIET|RETURN_ON_ERROR))
+		return false;
+
+	if (addr == 0)
+		return true;
+
+	if (!readmem(addr, PHYSADDR, &os_info,
+		    offsetof(struct os_info, reserved), "s390x os_info header",
+		    QUIET|RETURN_ON_ERROR))
+		return false;
+
+	vm_info->__identity_base      = os_info.entry[OS_INFO_IDENTITY_BASE].val;
+	vm_info->__kaslr_offset       = os_info.entry[OS_INFO_KASLR_OFFSET].val;
+	vm_info->__kaslr_offset_phys  = os_info.entry[OS_INFO_KASLR_OFF_PHYS].val;
+	vm_info->amode31_start        = os_info.entry[OS_INFO_AMODE31_START].val;
+	vm_info->amode31_end          = os_info.entry[OS_INFO_AMODE31_END].val;
+
+	return true;
+}
+
+static bool vm_info_empty(struct vm_info *vm_info)
+{
+	return !vm_info->__kaslr_offset;
+}
+
+static bool is_read_proc_kcore(void)
+{
+	struct stat kcore_stat, fd_stat;
+	int kcore_fd, fd;
+	int rc;
+
+	rc = stat("/proc/kcore", &kcore_stat);
+	if (rc)
+		return false;
+
+	fd = REMOTE_MEMSRC() ? pc->sockfd : (ACTIVE() ? pc->mfd : pc->dfd);
+	rc = fstat(fd, &fd_stat);
+	if (rc)
+		return false;
+
+	return (fd_stat.st_ino == kcore_stat.st_ino) &&
+	       (fd_stat.st_dev == kcore_stat.st_dev);
+}
+
+static bool s390x_init_vm(void)
+{
+	struct vm_info vm_info;
+
+	if (is_read_proc_kcore()) {
+		if (!vmcoreinfo_read_vm_info(&vm_info))
+			return true;
+	} else {
+		if (!os_info_read_vm_info(&vm_info))
+			return false;
+	}
+	if (vm_info_empty(&vm_info))
+		return true;
+
+	machdep->identity_map_base		= vm_info.__identity_base;
+	machdep->kvbase				= vm_info.__kaslr_offset;
+	machdep->machspec->__kaslr_offset_phys	= vm_info.__kaslr_offset_phys;
+	machdep->machspec->amode31_start	= vm_info.amode31_start;
+	machdep->machspec->amode31_end		= vm_info.amode31_end;
+
+	machdep->is_kvaddr			= s390x_vr_is_kvaddr;
+	machdep->machspec->virt_to_phys		= s390x_vr_VTOP;
+	machdep->machspec->phys_to_virt		= s390x_vr_PTOV;
+	machdep->machspec->is_vmalloc_addr	= s390x_vr_IS_VMALLOC_ADDR;
+
+	return true;
+}
+
+static ulong s390x_generic_VTOP(ulong vaddr)
+{
+	return vaddr - machdep->kvbase;
+}
+
+static ulong s390x_generic_PTOV(ulong paddr)
+{
+	return paddr + machdep->kvbase;
+}
+
+static int s390x_generic_IS_VMALLOC_ADDR(ulong vaddr)
+{
+	return vt->vmalloc_start && vaddr >= vt->vmalloc_start;
+}
+
+static ulong s390x_vr_VTOP(ulong vaddr)
+{
+	if (vaddr < LOWCORE_SIZE)
+		return vaddr;
+	if ((vaddr < machdep->machspec->amode31_end) &&
+	    (vaddr >= machdep->machspec->amode31_start))
+		return vaddr;
+	if (vaddr < machdep->kvbase)
+		return vaddr - machdep->identity_map_base;
+	return vaddr - machdep->kvbase + machdep->machspec->__kaslr_offset_phys;
+}
+
+static ulong s390x_vr_PTOV(ulong paddr)
+{
+	return paddr + machdep->identity_map_base;
+}
+
+static int s390x_vr_IS_VMALLOC_ADDR(ulong vaddr)
+{
+	return (vaddr >= vt->vmalloc_start && vaddr < machdep->kvbase);
+}
+
+ulong s390x_VTOP(ulong vaddr)
+{
+	return machdep->machspec->virt_to_phys(vaddr);
+}
+
+ulong s390x_PTOV(ulong paddr)
+{
+	return machdep->machspec->phys_to_virt(paddr);
+}
+
+int s390x_IS_VMALLOC_ADDR(ulong vaddr)
+{
+	return machdep->machspec->is_vmalloc_addr(vaddr);
+}
+
 /*
  *  Do all necessary machine-specific setup here.  This is called several
  *  times during initialization.
@@ -560,6 +778,7 @@ s390x_init(int when)
 		machdep->process_elf_notes = s390x_process_elf_notes;
 		break;
 	case PRE_SYMTAB:
+		machdep->machspec = &s390x_machine_specific;
 		machdep->verify_symbol = s390x_verify_symbol;
 		if (pc->flags & KERNEL_DEBUG_QUERY)
 			return;
@@ -587,6 +806,8 @@ s390x_init(int when)
 		machdep->kvbase = 0;
 		machdep->identity_map_base = 0;
 		machdep->is_kvaddr =  generic_is_kvaddr;
+		if (!s390x_init_vm())
+			error(FATAL, "cannot initialize VM parameters.");
 		machdep->is_uvaddr =  s390x_is_uvaddr;
 		machdep->eframe_search = s390x_eframe_search;
 		machdep->back_trace = s390x_back_trace_cmd;
@@ -681,7 +902,9 @@ s390x_dump_machdep_table(ulong arg)
 	fprintf(fp, "         dis_filter: s390x_dis_filter()\n");
 	fprintf(fp, "           cmd_mach: s390x_cmd_mach()\n");
 	fprintf(fp, "       get_smp_cpus: s390x_get_smp_cpus()\n");
-	fprintf(fp, "          is_kvaddr: generic_is_kvaddr()\n");
+	fprintf(fp, "          is_kvaddr: %s()\n", machdep->is_kvaddr == s390x_vr_is_kvaddr ?
+					  "s390x_vr_is_kvaddr" :
+					  "generic_is_kvaddr");
 	fprintf(fp, "          is_uvaddr: s390x_is_uvaddr()\n");
 	fprintf(fp, "       verify_paddr: generic_verify_paddr()\n");
 	fprintf(fp, "  get_kvaddr_ranges: s390x_get_kvaddr_ranges()\n");
@@ -702,6 +925,12 @@ s390x_dump_machdep_table(ulong arg)
 	fprintf(fp, "           machspec: %lx\n", (ulong)machdep->machspec);
 }
 
+static int
+s390x_vr_is_kvaddr(ulong vaddr)
+{
+	return (vaddr < LOWCORE_SIZE) || (vaddr >= machdep->identity_map_base);
+}
+
 /*
  * Check if address is in context's address space
  */
-- 
2.40.1
--
Crash-utility mailing list -- devel@xxxxxxxxxxxxxxxxxxxxxxxxxxx
To unsubscribe send an email to devel-leave@xxxxxxxxxxxxxxxxxxxxxxxxxxx
https://${domain_name}/admin/lists/devel.lists.crash-utility.osci.io/
Contribution Guidelines: https://github.com/crash-utility/crash/wiki




[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux