Thank you for the update, qiwu.

On Wed, Jul 31, 2024 at 7:45 PM <devel-request@lists.crash-utility.osci.io> wrote:
Date: Wed, 31 Jul 2024 09:20:30 -0000
From: qiwu.chen@transsion.com
Subject: [Crash-utility] [PATCH v2] arm64: fix regression for the
        determination of section_size_bits
To: devel@lists.crash-utility.osci.io
Message-ID: <20240731092030.17290.83380@lists.crash-utility.osci.io>
Content-Type: text/plain; charset="utf-8"

The commit 568c6f04 will cause a regression issue for the determination of
section_size_bits on kernel version before android12-5.10 or Linux-v5.12.
The section_size_bits is supposed to be compatible with linux upstream and
android GKI version:
Before android12-5.10 or Linux-v5.12:
        SECTION_SIZE_BITS = 30

After android12-5.10 or Linux-v5.12:
    SECTION_SIZE_BITS = 27 when defined 4K_PAGES or 16K_PAGES.
    SECTION_SIZE_BITS = 29 when defined 64K_PAGES.

Introduce arm64_get_andriod_gki_version() to get Andriod GKI version by ut->release.
The Andriod GKI version is determined either by arm64_get_andriod_gki_version()
or the kernel config "CONFIG_ANDROID_KABI_RESERVE".

Fixes: 568c6f04 ("arm64: section_size_bits compatible with macro definitions")
Signed-off-by: qiwu.chen <qiwu.chen@transsion.com>
---
 arm64.c | 68 ++++++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 51 insertions(+), 17 deletions(-)

diff --git a/arm64.c b/arm64.c
index 78e6609..679f2ab 100644
--- a/arm64.c
+++ b/arm64.c
@@ -95,6 +95,13 @@ static void arm64_calc_KERNELPACMASK(void);
 static void arm64_recalc_KERNELPACMASK(void);
 static int arm64_get_vmcoreinfo(unsigned long *vaddr, const char *label, int base);

+/* Andriod GKI version definition */
+struct andriod_gki_version {
+       int kernel_version;
+       int kernel_patch_level;
+       int android_version;
+};
+

This is specific version information related to Android, to be honest, I'm not very familiar with Android things.

Anyway, I'm wondering if it's possible to not add the specific Android version information?


 struct kernel_range {
        unsigned long modules_vaddr, modules_end;
        unsigned long vmalloc_start_addr, vmalloc_end;
@@ -1615,6 +1622,30 @@ arm64_calc_phys_offset(void)
                fprintf(fp, "using %lx as phys_offset\n", ms->phys_offset);
 }

+/*
+ * Determine Andriod GKI vmcore by reading "android" from ut->release.
+ * The prefix of Andriod GKI release version is:
+ *     Kernel Version - Android release version
+ * For example:
+ *     5.10.209-android12, 5.15.148-android13
+ */
+static bool arm64_get_andriod_gki_version(struct andriod_gki_version *version)
+{
+       char *p;
+       struct new_utsname *uts = &kt->utsname;
+
+       if ((p = strstr(uts->release, "android"))) {
+               sscanf(uts->release, "%d.%d", &version->kernel_version, &version->kernel_patch_level);
+               sscanf(p, "android%d", &version->android_version);
+               if (CRASHDEBUG(1))
+                       fprintf(fp, "andriod_gki_version: andriod%d-%d.%d\n",
+                           version->android_version, version->kernel_version, version->kernel_patch_level);
+               return true;
+       }
+
+       return false;
+}
+
 /*
  *  Determine SECTION_SIZE_BITS either by reading VMCOREINFO or the kernel
  *  config, otherwise use the 64-bit ARM default definiton.
@@ -1624,8 +1655,17 @@ arm64_get_section_size_bits(void)
 {
        int ret;
        char *string;
+       bool is_ikconfig_avail;
+       struct andriod_gki_version ver = {0};

-       if (THIS_KERNEL_VERSION >= LINUX(5,12,0)) {
+       if (arm64_get_vmcoreinfo(&machdep->section_size_bits, "NUMBER(SECTION_SIZE_BITS)", NUM_DEC))
+               goto exit;
+
+       is_ikconfig_avail = kt->ikconfig_flags & IKCONFIG_AVAIL ? TRUE : FALSE;
+       /* The commit reduce section size for arm64 sparsemem is introduced since linux-v5.12 and android-12-5.10 */
+       if (THIS_KERNEL_VERSION >= LINUX(5,12,0) ||
+           (is_ikconfig_avail && get_kernel_config("CONFIG_ANDROID_KABI_RESERVE", NULL) == IKCONFIG_Y) ||
+           (arm64_get_andriod_gki_version(&ver) && (ver.kernel_version * 100 + ver.kernel_patch_level >= 510) && ver.android_version >= 12)) {

It's not a good idea to decide how your code should be executed by checking version information, although similar code exists in crash tools, I would not recommend this way, unless we have no better solutions. Could you please investigate it more?

Thanks
Lianbo
 
                if (machdep->pagesize == 65536)
                        machdep->section_size_bits = _SECTION_SIZE_BITS_5_12_64K;
                else
@@ -1633,24 +1673,18 @@ arm64_get_section_size_bits(void)
        } else
                machdep->section_size_bits = _SECTION_SIZE_BITS;

-       if (arm64_get_vmcoreinfo(&machdep->section_size_bits, "NUMBER(SECTION_SIZE_BITS)", NUM_DEC)) {
-               /* nothing */
-       } else if (kt->ikconfig_flags & IKCONFIG_AVAIL) {
-               if ((ret = get_kernel_config("CONFIG_MEMORY_HOTPLUG", NULL)) == IKCONFIG_Y) {
-                       if ((ret = get_kernel_config("CONFIG_HOTPLUG_SIZE_BITS", &string)) == IKCONFIG_STR)
-                               machdep->section_size_bits = atol(string);
-               }
-
-               /* arm64: reduce section size for sparsemem */
-               if ((ret = get_kernel_config("CONFIG_ARM64_4K_PAGES", NULL)) == IKCONFIG_Y
-                       || (ret = get_kernel_config("CONFIG_ARM64_16K_PAGES", NULL)) == IKCONFIG_Y)
-                       machdep->section_size_bits = _SECTION_SIZE_BITS_5_12;
-               else if ((ret = get_kernel_config("CONFIG_ARM64_64K_PAGES", NULL)) == IKCONFIG_Y)
-                       machdep->section_size_bits = _SECTION_SIZE_BITS_5_12_64K;
+       /* section_size_bits for arm64 vendor special case */
+       if (is_ikconfig_avail && get_kernel_config("CONFIG_MEMORY_HOTPLUG", NULL) == IKCONFIG_Y) {
+               if (get_kernel_config("CONFIG_HOTPLUG_SIZE_BITS", &string) == IKCONFIG_STR)
+                       machdep->section_size_bits = atol(string);
        }

-       if (CRASHDEBUG(1))
-               fprintf(fp, "SECTION_SIZE_BITS: %ld\n", machdep->section_size_bits);
+exit:
+       if (machdep->section_size_bits) {
+               if (CRASHDEBUG(1))
+                       fprintf(fp, "SECTION_SIZE_BITS: %ld\n", machdep->section_size_bits);
+       } else
+               error(FATAL, "cannot determine SECTION_SIZE_BITS\n");
 }

 /*
--
2.25.1