All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv2 0/3] arm64: make phys_to_virt() correct
@ 2021-12-17  4:19 Pingfan Liu
  2021-12-17  4:19 ` [PATCHv2 1/3] arm64: make phys_offset signed Pingfan Liu
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Pingfan Liu @ 2021-12-17  4:19 UTC (permalink / raw)
  To: kexec; +Cc: Simon Horman, Philipp Rudo, Pingfan Liu

Currently phys_to_virt() does not work well on 52-bits VA arm64 kernel.
One issue is contributed by phys_offset not signed.
The other is contributed by wrong page_offset.

v1 -> v2
Fix broken patch [2/3] in v1
Move arch_scan_vmcoreinfo declaration to util_lib/include/elf_info.h
Using UINT64_MAX instread of 0xffffffffffffffff



Pingfan Liu (3):
  arm64: make phys_offset signed
  arm64/crashdump: unify routine to get page_offset
  arm64: read VA_BITS from kcore for 52-bits VA kernel

 kexec/arch/arm64/crashdump-arm64.c | 23 +-------------
 kexec/arch/arm64/kexec-arm64.c     | 48 +++++++++++++++++++++++-------
 kexec/arch/arm64/kexec-arm64.h     |  3 +-
 util_lib/elf_info.c                |  7 ++++-
 util_lib/include/elf_info.h        |  3 +-
 5 files changed, 48 insertions(+), 36 deletions(-)

-- 
2.31.1


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

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCHv2 1/3] arm64: make phys_offset signed
  2021-12-17  4:19 [PATCHv2 0/3] arm64: make phys_to_virt() correct Pingfan Liu
@ 2021-12-17  4:19 ` Pingfan Liu
  2021-12-17  4:19 ` [PATCHv2 2/3] arm64/crashdump: unify routine to get page_offset Pingfan Liu
  2021-12-17  4:19 ` [PATCHv2 3/3] arm64: read VA_BITS from kcore for 52-bits VA kernel Pingfan Liu
  2 siblings, 0 replies; 4+ messages in thread
From: Pingfan Liu @ 2021-12-17  4:19 UTC (permalink / raw)
  To: kexec; +Cc: Simon Horman, Philipp Rudo, Pingfan Liu

After kernel commit 7bc1a0f9e176 ("arm64: mm: use single quantity to
represent the PA to VA translation"), phys_offset can be negative if
running 52-bits kernel on 48-bits hardware.

So changing phys_offset from unsigned to signed.

Signed-off-by: Pingfan Liu <piliu@redhat.com>
---
 kexec/arch/arm64/kexec-arm64.c | 8 ++++----
 kexec/arch/arm64/kexec-arm64.h | 2 +-
 util_lib/elf_info.c            | 2 +-
 util_lib/include/elf_info.h    | 2 +-
 4 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
index 6f572ed..7373fa3 100644
--- a/kexec/arch/arm64/kexec-arm64.c
+++ b/kexec/arch/arm64/kexec-arm64.c
@@ -859,7 +859,7 @@ void add_segment(struct kexec_info *info, const void *buf, size_t bufsz,
 	add_segment_phys_virt(info, buf, bufsz, base, memsz, 1);
 }
 
-static inline void set_phys_offset(uint64_t v, char *set_method)
+static inline void set_phys_offset(long v, char *set_method)
 {
 	if (arm64_mem.phys_offset == arm64_mem_ngv
 		|| v < arm64_mem.phys_offset) {
@@ -928,7 +928,7 @@ static int get_page_offset(void)
  * from VMCOREINFO note inside 'kcore'.
  */
 
-static int get_phys_offset_from_vmcoreinfo_pt_note(unsigned long *phys_offset)
+static int get_phys_offset_from_vmcoreinfo_pt_note(long *phys_offset)
 {
 	int fd, ret = 0;
 
@@ -948,7 +948,7 @@ static int get_phys_offset_from_vmcoreinfo_pt_note(unsigned long *phys_offset)
  * from PT_LOADs inside 'kcore'.
  */
 
-int get_phys_base_from_pt_load(unsigned long *phys_offset)
+int get_phys_base_from_pt_load(long *phys_offset)
 {
 	int i, fd, ret;
 	unsigned long long phys_start;
@@ -997,7 +997,7 @@ static bool to_be_excluded(char *str)
 int get_memory_ranges(struct memory_range **range, int *ranges,
 	unsigned long kexec_flags)
 {
-	unsigned long phys_offset = UINT64_MAX;
+	long phys_offset = (long)UINT64_MAX;
 	FILE *fp;
 	const char *iomem = proc_iomem();
 	char line[MAX_LINE], *str;
diff --git a/kexec/arch/arm64/kexec-arm64.h b/kexec/arch/arm64/kexec-arm64.h
index ed447ac..1844b67 100644
--- a/kexec/arch/arm64/kexec-arm64.h
+++ b/kexec/arch/arm64/kexec-arm64.h
@@ -58,7 +58,7 @@ extern off_t initrd_size;
  */
 
 struct arm64_mem {
-	uint64_t phys_offset;
+	long phys_offset;
 	uint64_t text_offset;
 	uint64_t image_size;
 	uint64_t vp_offset;
diff --git a/util_lib/elf_info.c b/util_lib/elf_info.c
index 51d8b92..5574c7f 100644
--- a/util_lib/elf_info.c
+++ b/util_lib/elf_info.c
@@ -1236,7 +1236,7 @@ int read_elf(int fd)
 	return 0;
 }
 
-int read_phys_offset_elf_kcore(int fd, unsigned long *phys_off)
+int read_phys_offset_elf_kcore(int fd, long *phys_off)
 {
 	int ret;
 
diff --git a/util_lib/include/elf_info.h b/util_lib/include/elf_info.h
index 4bc9279..f550d86 100644
--- a/util_lib/include/elf_info.h
+++ b/util_lib/include/elf_info.h
@@ -28,7 +28,7 @@ int get_pt_load(int idx,
 	unsigned long long *phys_end,
 	unsigned long long *virt_start,
 	unsigned long long *virt_end);
-int read_phys_offset_elf_kcore(int fd, unsigned long *phys_off);
+int read_phys_offset_elf_kcore(int fd, long *phys_off);
 int read_elf(int fd);
 void dump_dmesg(int fd, void (*handler)(char*, unsigned int));
 
-- 
2.31.1


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

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCHv2 2/3] arm64/crashdump: unify routine to get page_offset
  2021-12-17  4:19 [PATCHv2 0/3] arm64: make phys_to_virt() correct Pingfan Liu
  2021-12-17  4:19 ` [PATCHv2 1/3] arm64: make phys_offset signed Pingfan Liu
@ 2021-12-17  4:19 ` Pingfan Liu
  2021-12-17  4:19 ` [PATCHv2 3/3] arm64: read VA_BITS from kcore for 52-bits VA kernel Pingfan Liu
  2 siblings, 0 replies; 4+ messages in thread
From: Pingfan Liu @ 2021-12-17  4:19 UTC (permalink / raw)
  To: kexec; +Cc: Simon Horman, Philipp Rudo, Pingfan Liu

There are two funcs to get page_offset:
  get_kernel_page_offset()
  get_page_offset()

Since get_kernel_page_offset() does not observe the kernel formula, and
remove it. Unify them in order to introduce 52-bits VA kernel more
easily in the coming patch.

Signed-off-by: Pingfan Liu <piliu@redhat.com>
---
 kexec/arch/arm64/crashdump-arm64.c | 23 +----------------------
 kexec/arch/arm64/kexec-arm64.c     |  8 ++++----
 kexec/arch/arm64/kexec-arm64.h     |  1 +
 3 files changed, 6 insertions(+), 26 deletions(-)

diff --git a/kexec/arch/arm64/crashdump-arm64.c b/kexec/arch/arm64/crashdump-arm64.c
index a02019a..0a8d44c 100644
--- a/kexec/arch/arm64/crashdump-arm64.c
+++ b/kexec/arch/arm64/crashdump-arm64.c
@@ -46,27 +46,6 @@ static struct crash_elf_info elf_info = {
 	.machine	= EM_AARCH64,
 };
 
-/*
- * Note: The returned value is correct only if !CONFIG_RANDOMIZE_BASE.
- */
-static uint64_t get_kernel_page_offset(void)
-{
-	int i;
-
-	if (elf_info.kern_vaddr_start == UINT64_MAX)
-		return UINT64_MAX;
-
-	/* Current max virtual memory range is 48-bits. */
-	for (i = 48; i > 0; i--)
-		if (!(elf_info.kern_vaddr_start & (1UL << i)))
-			break;
-
-	if (i <= 0)
-		return UINT64_MAX;
-	else
-		return UINT64_MAX << i;
-}
-
 /*
  * iomem_range_callback() - callback called for each iomem region
  * @data: not used
@@ -198,7 +177,7 @@ int load_crashdump_segments(struct kexec_info *info)
 	if (err)
 		return EFAILED;
 
-	elf_info.page_offset = get_kernel_page_offset();
+	get_page_offset(&elf_info.page_offset);
 	dbgprintf("%s: page_offset:   %016llx\n", __func__,
 			elf_info.page_offset);
 
diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
index 7373fa3..037e51c 100644
--- a/kexec/arch/arm64/kexec-arm64.c
+++ b/kexec/arch/arm64/kexec-arm64.c
@@ -909,7 +909,7 @@ static int get_va_bits(void)
  * get_page_offset - Helper for getting PAGE_OFFSET
  */
 
-static int get_page_offset(void)
+int get_page_offset(unsigned long *page_offset)
 {
 	int ret;
 
@@ -917,8 +917,8 @@ static int get_page_offset(void)
 	if (ret < 0)
 		return ret;
 
-	page_offset = (0xffffffffffffffffUL) << (va_bits - 1);
-	dbgprintf("page_offset : %lx\n", page_offset);
+	*page_offset = (0xffffffffffffffffUL) << (va_bits - 1);
+	dbgprintf("page_offset : %lx\n", *page_offset);
 
 	return 0;
 }
@@ -954,7 +954,7 @@ int get_phys_base_from_pt_load(long *phys_offset)
 	unsigned long long phys_start;
 	unsigned long long virt_start;
 
-	ret = get_page_offset();
+	ret = get_page_offset(&page_offset);
 	if (ret < 0)
 		return ret;
 
diff --git a/kexec/arch/arm64/kexec-arm64.h b/kexec/arch/arm64/kexec-arm64.h
index 1844b67..ed99d9d 100644
--- a/kexec/arch/arm64/kexec-arm64.h
+++ b/kexec/arch/arm64/kexec-arm64.h
@@ -69,6 +69,7 @@ extern struct arm64_mem arm64_mem;
 
 uint64_t get_phys_offset(void);
 uint64_t get_vp_offset(void);
+int get_page_offset(unsigned long *offset);
 
 static inline void reset_vp_offset(void)
 {
-- 
2.31.1


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

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCHv2 3/3] arm64: read VA_BITS from kcore for 52-bits VA kernel
  2021-12-17  4:19 [PATCHv2 0/3] arm64: make phys_to_virt() correct Pingfan Liu
  2021-12-17  4:19 ` [PATCHv2 1/3] arm64: make phys_offset signed Pingfan Liu
  2021-12-17  4:19 ` [PATCHv2 2/3] arm64/crashdump: unify routine to get page_offset Pingfan Liu
@ 2021-12-17  4:19 ` Pingfan Liu
  2 siblings, 0 replies; 4+ messages in thread
From: Pingfan Liu @ 2021-12-17  4:19 UTC (permalink / raw)
  To: kexec; +Cc: Simon Horman, Philipp Rudo, Pingfan Liu

phys_to_virt() calculates virtual address. As a important factor,
page_offset is excepted to be accurate.

Since arm64 kernel exposes va_bits through vmcore, using it.

Signed-off-by: Pingfan Liu <piliu@redhat.com>
---
 kexec/arch/arm64/kexec-arm64.c | 34 ++++++++++++++++++++++++++++++----
 util_lib/elf_info.c            |  5 +++++
 util_lib/include/elf_info.h    |  1 +
 3 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
index 037e51c..86aadf0 100644
--- a/kexec/arch/arm64/kexec-arm64.c
+++ b/kexec/arch/arm64/kexec-arm64.c
@@ -54,7 +54,7 @@
 static bool try_read_phys_offset_from_kcore = false;
 
 /* Machine specific details. */
-static int va_bits;
+static int va_bits = -1;
 static unsigned long page_offset;
 
 /* Global varables the core kexec routines expect. */
@@ -876,7 +876,18 @@ static inline void set_phys_offset(long v, char *set_method)
 
 static int get_va_bits(void)
 {
-	unsigned long long stext_sym_addr = get_kernel_sym("_stext");
+	unsigned long long stext_sym_addr;
+
+	/*
+	 * if already got from kcore
+	 */
+	if (va_bits != -1)
+		goto out;
+
+
+	/* For kernel older than v4.19 */
+	fprintf(stderr, "Warning, can't get the VA_BITS from kcore\n");
+	stext_sym_addr = get_kernel_sym("_stext");
 
 	if (stext_sym_addr == 0) {
 		fprintf(stderr, "Can't get the symbol of _stext.\n");
@@ -900,6 +911,7 @@ static int get_va_bits(void)
 		return -1;
 	}
 
+out:
 	dbgprintf("va_bits : %d\n", va_bits);
 
 	return 0;
@@ -917,14 +929,27 @@ int get_page_offset(unsigned long *page_offset)
 	if (ret < 0)
 		return ret;
 
-	*page_offset = (0xffffffffffffffffUL) << (va_bits - 1);
+	if (va_bits < 52)
+		*page_offset = UINT64_MAX << (va_bits - 1);
+	else
+		*page_offset = UINT64_MAX << va_bits;
+
 	dbgprintf("page_offset : %lx\n", *page_offset);
 
 	return 0;
 }
 
+static void arm64_scan_vmcoreinfo(char *pos)
+{
+	const char *str;
+
+	str = "NUMBER(VA_BITS)=";
+	if (memcmp(str, pos, strlen(str)) == 0)
+		va_bits = strtoul(pos + strlen(str), NULL, 10);
+}
+
 /**
- * get_phys_offset_from_vmcoreinfo_pt_note - Helper for getting PHYS_OFFSET
+ * get_phys_offset_from_vmcoreinfo_pt_note - Helper for getting PHYS_OFFSET (and va_bits)
  * from VMCOREINFO note inside 'kcore'.
  */
 
@@ -937,6 +962,7 @@ static int get_phys_offset_from_vmcoreinfo_pt_note(long *phys_offset)
 		return EFAILED;
 	}
 
+	arch_scan_vmcoreinfo = arm64_scan_vmcoreinfo;
 	ret = read_phys_offset_elf_kcore(fd, phys_offset);
 
 	close(fd);
diff --git a/util_lib/elf_info.c b/util_lib/elf_info.c
index 5574c7f..d252eff 100644
--- a/util_lib/elf_info.c
+++ b/util_lib/elf_info.c
@@ -310,6 +310,8 @@ int get_pt_load(int idx,
 
 #define NOT_FOUND_LONG_VALUE		(-1)
 
+void (*arch_scan_vmcoreinfo)(char *pos);
+
 void scan_vmcoreinfo(char *start, size_t size)
 {
 	char *last = start + size - 1;
@@ -551,6 +553,9 @@ void scan_vmcoreinfo(char *start, size_t size)
 			}
 		}
 
+		if (arch_scan_vmcoreinfo != NULL)
+			(*arch_scan_vmcoreinfo)(pos);
+
 		if (last_line)
 			break;
 	}
diff --git a/util_lib/include/elf_info.h b/util_lib/include/elf_info.h
index f550d86..fdf4c3d 100644
--- a/util_lib/include/elf_info.h
+++ b/util_lib/include/elf_info.h
@@ -31,5 +31,6 @@ int get_pt_load(int idx,
 int read_phys_offset_elf_kcore(int fd, long *phys_off);
 int read_elf(int fd);
 void dump_dmesg(int fd, void (*handler)(char*, unsigned int));
+extern void (*arch_scan_vmcoreinfo)(char *pos);
 
 #endif /* ELF_INFO_H */
-- 
2.31.1


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

^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2021-12-17  4:20 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-17  4:19 [PATCHv2 0/3] arm64: make phys_to_virt() correct Pingfan Liu
2021-12-17  4:19 ` [PATCHv2 1/3] arm64: make phys_offset signed Pingfan Liu
2021-12-17  4:19 ` [PATCHv2 2/3] arm64/crashdump: unify routine to get page_offset Pingfan Liu
2021-12-17  4:19 ` [PATCHv2 3/3] arm64: read VA_BITS from kcore for 52-bits VA kernel Pingfan Liu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.