[PATCH v2] Fix "ps/vm" commands to display the memory usage for exiting tasks
by Lianbo Jiang
When a task is exiting, usually kernel marks its flags as 'PF_EXITING',
but even so, sometimes the mm_struct has not been freed, it might still
be valid. For such tasks, the "ps/vm" commands won't display the memory
usage. For example:
crash> ps 47070
PID PPID CPU TASK ST %MEM VSZ RSS COMM
47070 1 0 ffff9ba7c4910000 UN 0.0 0 0 ra_ris.parse
crash> vm 47070
PID: 47070 TASK: ffff9ba7c4910000 CPU: 0 COMMAND: "ra_ris.parse"
MM PGD RSS TOTAL_VM
0 0 0k 0k
To be honest, this is a corner case, but it has already occurred in
actual production environments. Given that, let's allow the "ps/vm"
commands to try to display the memory usage for this case, but it does
not guarantee that it can work well at any time, which still depends on
how far the mm_struct deconstruction has proceeded.
With the patch:
crash> ps 47070
PID PPID CPU TASK ST %MEM VSZ RSS COMM
47070 1 0 ffff9ba7c4910000 UN 90.8 38461228 31426444 ra_ris.parse
crash> vm 47070
PID: 47070 TASK: ffff9ba7c4910000 CPU: 0 COMMAND: "ra_ris.parse"
MM PGD RSS TOTAL_VM
ffff9bad6e873840 ffff9baee0544000 31426444k 38461228k
VMA START END FLAGS FILE
ffff9bafdbe1d6c8 400000 8c5000 8000875 /data1/rishome/ra_cu_cn_412/sbin/ra_ris.parse
...
Reported-by: Buland Kumar Singh <bsingh(a)redhat.com>
Signed-off-by: Lianbo Jiang <lijiang(a)redhat.com>
---
memory.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/memory.c b/memory.c
index 5d76c5d7fe6f..86ccec5e2bac 100644
--- a/memory.c
+++ b/memory.c
@@ -4792,10 +4792,11 @@ get_task_mem_usage(ulong task, struct task_mem_usage *tm)
{
struct task_context *tc;
long rss = 0, rss_cache = 0;
+ int mm_count = 0;
BZERO(tm, sizeof(struct task_mem_usage));
- if (IS_ZOMBIE(task) || IS_EXITING(task))
+ if (IS_ZOMBIE(task))
return;
tc = task_to_context(task);
@@ -4808,6 +4809,11 @@ get_task_mem_usage(ulong task, struct task_mem_usage *tm)
if (!task_mm(task, TRUE))
return;
+ mm_count = INT(tt->mm_struct + OFFSET(mm_struct_mm_count));
+
+ if (IS_EXITING(task) && mm_count <= 0)
+ return;
+
if (VALID_MEMBER(mm_struct_rss))
/*
* mm_struct.rss or mm_struct._rss exist.
--
2.37.1
1 year, 3 months
[PATCH] Fix "ps/vm" commands to display the memory usage for exiting tasks
by Lianbo Jiang
When a task is exiting, usually kernel marks its flags as 'PF_EXITING',
but even so, sometimes the mm_struct has not been freed, it might still
be valid. For such tasks, the "ps/vm" commands won't display the memory
usage. For example:
crash> ps 47070
PID PPID CPU TASK ST %MEM VSZ RSS COMM
47070 1 0 ffff9ba7c4910000 UN 0.0 0 0 ra_ris.parse
crash> vm 47070
PID: 47070 TASK: ffff9ba7c4910000 CPU: 0 COMMAND: "ra_ris.parse"
MM PGD RSS TOTAL_VM
0 0 0k 0k
To be honest, this is a corner case, but it has already occurred in
actual production environments. Given that, let's allow the "ps/vm"
commands to try to display the memory usage for this case, but it does
not guarantee that it can work well at any time, which still depends on
how far the mm_struct deconstruction has proceeded.
With the patch:
crash> ps 47070
PID PPID CPU TASK ST %MEM VSZ RSS COMM
47070 1 0 ffff9ba7c4910000 UN 90.8 38461228 31426444 ra_ris.parse
crash> vm 47070
PID: 47070 TASK: ffff9ba7c4910000 CPU: 0 COMMAND: "ra_ris.parse"
MM PGD RSS TOTAL_VM
ffff9bad6e873840 ffff9baee0544000 31426444k 38461228k
VMA START END FLAGS FILE
ffff9bafdbe1d6c8 400000 8c5000 8000875 /data1/rishome/ra_cu_cn_412/sbin/ra_ris.parse
...
Reported-by: Buland Kumar Singh <bsingh(a)redhat.com>
Signed-off-by: Lianbo Jiang <lijiang(a)redhat.com>
---
memory.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/memory.c b/memory.c
index 5d76c5d7fe6f..7d59c0555a0e 100644
--- a/memory.c
+++ b/memory.c
@@ -4792,10 +4792,12 @@ get_task_mem_usage(ulong task, struct task_mem_usage *tm)
{
struct task_context *tc;
long rss = 0, rss_cache = 0;
+ int mm_count = 0;
+ ulong addr;
BZERO(tm, sizeof(struct task_mem_usage));
- if (IS_ZOMBIE(task) || IS_EXITING(task))
+ if (IS_ZOMBIE(task))
return;
tc = task_to_context(task);
@@ -4805,7 +4807,14 @@ get_task_mem_usage(ulong task, struct task_mem_usage *tm)
tm->mm_struct_addr = tc->mm_struct;
- if (!task_mm(task, TRUE))
+ if (!(addr = task_mm(task, TRUE)))
+ return;
+
+ if (!readmem(addr + OFFSET(mm_struct_mm_count), KVADDR, &mm_count,
+ sizeof(int), "mm_struct mm_count", RETURN_ON_ERROR))
+ return;
+
+ if (IS_EXITING(task) && mm_count <= 0)
return;
if (VALID_MEMBER(mm_struct_rss))
--
2.37.1
1 year, 3 months
[Crash-utility PATCH V2] RISCV64: Add KASLR support
by Song Shuai
From: Song Shuai <suagrfillet(a)gmail.com>
This patch adds KASLR support for Crash to analyze KASLR-ed vmcore
since RISC-V Linux is already sufficiently prepared for KASLR [1].
With this patch, even if the Crash '--kaslr' option is not set or Linux
CONFIG_RANDOMIZE_BASE is not configured, the 'derive_kaslr_offset()'
function will always work to calculate 'kt->relocate' which serves to
update the kernel virtual address.
Testing in Qemu rv64 virt, kernel log outputed the kernel offset:
[ 121.214447] SMP: stopping secondary CPUs
[ 121.215445] Kernel Offset: 0x37c00000 from 0xffffffff80000000
[ 121.216312] Starting crashdump kernel...
[ 121.216585] Will call new kernel at 94800000 from hart id 0
[ 121.216834] FDT image at 9c7fd000
[ 121.216982] Bye...
Running crash with `-d 1` option and without `--kaslr` option,
we get the right `kt->relocate` and kernel link addr:
$ ../crash/crash -d 1 vmlinux vmcore_kaslr_0815
...
KASLR:
_stext from vmlinux: ffffffff80002000
_stext from vmcoreinfo: ffffffffb7c02000
relocate: 37c00000 (892MB)
vmemmap : 0xff1c000000000000 - 0xff20000000000000
vmalloc : 0xff20000000000000 - 0xff60000000000000
mudules : 0xffffffff3952f000 - 0xffffffffb7c00000
lowmem : 0xff60000000000000 -
kernel link addr : 0xffffffffb7c00000
...
KERNEL: /home/song/9_linux/linux/00_rv_kaslr/vmlinux
DUMPFILE: /tmp/hello/vmcore_kaslr_0815
CPUS: 2
DATE: Tue Aug 15 16:36:15 CST 2023
UPTIME: 00:02:01
LOAD AVERAGE: 0.40, 0.23, 0.09
TASKS: 63
NODENAME: stage4.fedoraproject.org
RELEASE: 6.5.0-rc3-00008-gad18dee423ac
VERSION: #17 SMP Tue Aug 15 14:41:12 CST 2023
MACHINE: riscv64 (unknown Mhz)
MEMORY: 511.8 MB
PANIC: "Kernel panic - not syncing: sysrq triggered crash"
PID: 160
COMMAND: "bash"
TASK: ff6000000152bac0 [THREAD_INFO: ff6000000152bac0]
CPU: 1
STATE: TASK_RUNNING (PANIC)
crash>
[1]: https://lore.kernel.org/linux-riscv/20230722123850.634544-1-alexghiti@riv...
Signed-off-by: Song Shuai <suagrfillet(a)gmail.com>
Reviewed-by: Guo Ren <guoren(a)kernel.org>
---
Changes since V1:
https://lore.kernel.org/linux-riscv/20230815104800.705753-1-songshuaishua...
- supplement the output of my Crash test in the commit-msg
- add the Reviewed-by from Guo
---
main.c | 2 +-
riscv64.c | 11 +++++++++++
symbols.c | 4 ++--
3 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/main.c b/main.c
index b278c22..0c6e595 100644
--- a/main.c
+++ b/main.c
@@ -228,7 +228,7 @@ main(int argc, char **argv)
} else if (STREQ(long_options[option_index].name, "kaslr")) {
if (!machine_type("X86_64") &&
!machine_type("ARM64") && !machine_type("X86") &&
- !machine_type("S390X"))
+ !machine_type("S390X") && !machine_type("RISCV64"))
error(INFO, "--kaslr not valid "
"with this machine type.\n");
else if (STREQ(optarg, "auto"))
diff --git a/riscv64.c b/riscv64.c
index a02f75a..288c7ae 100644
--- a/riscv64.c
+++ b/riscv64.c
@@ -378,6 +378,9 @@ static void riscv64_get_va_range(struct machine_specific *ms)
} else
goto error;
+ if ((kt->flags2 & KASLR) && (kt->flags & RELOC_SET))
+ ms->kernel_link_addr += (kt->relocate * -1);
+
/*
* From Linux 5.13, the kernel mapping is moved to the last 2GB
* of the address space, modules use the 2GB memory range right
@@ -1360,6 +1363,14 @@ riscv64_init(int when)
machdep->verify_paddr = generic_verify_paddr;
machdep->ptrs_per_pgd = PTRS_PER_PGD;
+
+ /*
+ * Even if CONFIG_RANDOMIZE_BASE is not configured,
+ * derive_kaslr_offset() should work and set
+ * kt->relocate to 0
+ */
+ if (!kt->relocate && !(kt->flags2 & (RELOC_AUTO|KASLR)))
+ kt->flags2 |= (RELOC_AUTO|KASLR);
break;
case PRE_GDB:
diff --git a/symbols.c b/symbols.c
index 876be7a..8e8b4c3 100644
--- a/symbols.c
+++ b/symbols.c
@@ -629,7 +629,7 @@ kaslr_init(void)
char *string;
if ((!machine_type("X86_64") && !machine_type("ARM64") && !machine_type("X86") &&
- !machine_type("S390X")) || (kt->flags & RELOC_SET))
+ !machine_type("S390X") && !machine_type("RISCV64")) || (kt->flags & RELOC_SET))
return;
if (!kt->vmcoreinfo._stext_SYMBOL &&
@@ -795,7 +795,7 @@ store_symbols(bfd *abfd, int dynamic, void *minisyms, long symcount,
} else if (!(kt->flags & RELOC_SET))
kt->flags |= RELOC_FORCE;
} else if (machine_type("X86_64") || machine_type("ARM64") ||
- machine_type("S390X")) {
+ machine_type("S390X") || machine_type("RISCV64")) {
if ((kt->flags2 & RELOC_AUTO) && !(kt->flags & RELOC_SET))
derive_kaslr_offset(abfd, dynamic, from,
fromend, size, store);
--
2.20.1
1 year, 3 months
Re: [Crash-utility] [PATCH] deduplicate kernel_version open-coded parser
by lijiang
On Tue, Aug 15, 2023 at 10:41 AM <crash-utility-request(a)redhat.com> wrote:
> Date: Mon, 14 Aug 2023 09:41:12 -0400
> From: Rafael Aquini <aquini(a)redhat.com>
> To: crash-utility(a)redhat.com
> Cc: raquini(a)redhat.com
> Subject: [Crash-utility] [PATCH] deduplicate kernel_version open-coded
> parser
> Message-ID: <20230814134112.232436-1-aquini(a)redhat.com>
>
> The code that parses kernel version from OSRELEASE/UTSRELEASE strings
> and populates the global kernel table is duplicated across the codebase
> for no good reason. This commit consolidates all the duplicated parsing
> code into a single method to remove the unnecessary duplicated code.
>
>
Thank you for the patch, Rafael.
And this looks good to me, so: Ack.
Thanks.
Lianbo
> Signed-off-by: Rafael Aquini <aquini(a)redhat.com>
> ---
> arm64.c | 27 +++----------------
> defs.h | 2 ++
> kernel.c | 77 ++++++++++++++++++++++++++-----------------------------
> riscv64.c | 25 ++----------------
> 4 files changed, 43 insertions(+), 88 deletions(-)
>
> diff --git a/arm64.c b/arm64.c
> index 67b1a22..39d5f04 100644
> --- a/arm64.c
> +++ b/arm64.c
> @@ -834,35 +834,14 @@ static struct kernel_va_range_handler
> kernel_va_range_handlers[] = {
> static unsigned long arm64_get_kernel_version(void)
> {
> char *string;
> - char buf[BUFSIZE];
> - char *p1, *p2;
>
> if (THIS_KERNEL_VERSION)
> return THIS_KERNEL_VERSION;
>
> - string = pc->read_vmcoreinfo("OSRELEASE");
> - if (string) {
> - strcpy(buf, string);
> -
> - p1 = p2 = buf;
> - while (*p2 != '.')
> - p2++;
> - *p2 = NULLCHAR;
> - kt->kernel_version[0] = atoi(p1);
> -
> - p1 = ++p2;
> - while (*p2 != '.')
> - p2++;
> - *p2 = NULLCHAR;
> - kt->kernel_version[1] = atoi(p1);
> -
> - p1 = ++p2;
> - while ((*p2 >= '0') && (*p2 <= '9'))
> - p2++;
> - *p2 = NULLCHAR;
> - kt->kernel_version[2] = atoi(p1);
> + if ((string = pc->read_vmcoreinfo("OSRELEASE"))) {
> + parse_kernel_version(string);
> + free(string);
> }
> - free(string);
> return THIS_KERNEL_VERSION;
> }
>
> diff --git a/defs.h b/defs.h
> index 5ee60f1..1925148 100644
> --- a/defs.h
> +++ b/defs.h
> @@ -6032,6 +6032,8 @@ void clone_bt_info(struct bt_info *, struct bt_info
> *, struct task_context *);
> void dump_kernel_table(int);
> void dump_bt_info(struct bt_info *, char *where);
> void dump_log(int);
> +void parse_kernel_version(char *);
> +
> #define LOG_LEVEL(v) ((v) & 0x07)
> #define SHOW_LOG_LEVEL (0x1)
> #define SHOW_LOG_DICT (0x2)
> diff --git a/kernel.c b/kernel.c
> index 2114700..988206b 100644
> --- a/kernel.c
> +++ b/kernel.c
> @@ -104,6 +104,38 @@ static void check_vmcoreinfo(void);
> static int is_pvops_xen(void);
> static int get_linux_banner_from_vmlinux(char *, size_t);
>
> +/*
> + * popuplate the global kernel table (kt) with kernel version
> + * information parsed from UTSNAME/OSRELEASE string
> + */
> +void
> +parse_kernel_version(char *str)
> +{
> + char *p1, *p2, separator;
> +
> + p1 = p2 = str;
> + while (*p2 != '.' && *p2 != '\0')
> + p2++;
> +
> + *p2 = NULLCHAR;
> + kt->kernel_version[0] = atoi(p1);
> + p1 = ++p2;
> + while (*p2 != '.' && *p2 != '-' && *p2 != '\0')
> + p2++;
> +
> + separator = *p2;
> + *p2 = NULLCHAR;
> + kt->kernel_version[1] = atoi(p1);
> +
> + if (separator == '.') {
> + p1 = ++p2;
> + while ((*p2 >= '0') && (*p2 <= '9'))
> + p2++;
> +
> + *p2 = NULLCHAR;
> + kt->kernel_version[2] = atoi(p1);
> + }
> +}
>
> /*
> * Gather a few kernel basics.
> @@ -112,7 +144,7 @@ void
> kernel_init()
> {
> int i, c;
> - char *p1, *p2, buf[BUFSIZE];
> + char buf[BUFSIZE];
> struct syment *sp1, *sp2;
> char *rqstruct;
> char *rq_timestamp_name = NULL;
> @@ -270,28 +302,7 @@ kernel_init()
> if (buf[64])
> buf[64] = NULLCHAR;
> if (ascii_string(kt->utsname.release)) {
> - char separator;
> -
> - p1 = p2 = buf;
> - while (*p2 != '.')
> - p2++;
> - *p2 = NULLCHAR;
> - kt->kernel_version[0] = atoi(p1);
> - p1 = ++p2;
> - while (*p2 != '.' && *p2 != '-' && *p2 != '\0')
> - p2++;
> - separator = *p2;
> - *p2 = NULLCHAR;
> - kt->kernel_version[1] = atoi(p1);
> - *p2 = separator;
> - if (*p2 == '.') {
> - p1 = ++p2;
> - while ((*p2 >= '0') && (*p2 <= '9'))
> - p2++;
> - *p2 = NULLCHAR;
> - kt->kernel_version[2] = atoi(p1);
> - } else
> - kt->kernel_version[2] = 0;
> + parse_kernel_version(buf);
>
> if (CRASHDEBUG(1))
> fprintf(fp, "base kernel version: %d.%d.%d\n",
> @@ -10973,8 +10984,6 @@ void
> get_log_from_vmcoreinfo(char *file)
> {
> char *string;
> - char buf[BUFSIZE];
> - char *p1, *p2;
> struct vmcoreinfo_data *vmc = &kt->vmcoreinfo;
>
> if (!(pc->flags2 & VMCOREINFO))
> @@ -10986,22 +10995,8 @@ get_log_from_vmcoreinfo(char *file)
> if ((string = pc->read_vmcoreinfo("OSRELEASE"))) {
> if (CRASHDEBUG(1))
> fprintf(fp, "OSRELEASE: %s\n", string);
> - strcpy(buf, string);
> - p1 = p2 = buf;
> - while (*p2 != '.')
> - p2++;
> - *p2 = NULLCHAR;
> - kt->kernel_version[0] = atoi(p1);
> - p1 = ++p2;
> - while (*p2 != '.')
> - p2++;
> - *p2 = NULLCHAR;
> - kt->kernel_version[1] = atoi(p1);
> - p1 = ++p2;
> - while ((*p2 >= '0') && (*p2 <= '9'))
> - p2++;
> - *p2 = NULLCHAR;
> - kt->kernel_version[2] = atoi(p1);
> +
> + parse_kernel_version(string);
>
> if (CRASHDEBUG(1))
> fprintf(fp, "base kernel version: %d.%d.%d\n",
> diff --git a/riscv64.c b/riscv64.c
> index 6b9a688..066cf2c 100644
> --- a/riscv64.c
> +++ b/riscv64.c
> @@ -259,33 +259,12 @@ riscv64_processor_speed(void)
> static unsigned long riscv64_get_kernel_version(void)
> {
> char *string;
> - char buf[BUFSIZE];
> - char *p1, *p2;
>
> if (THIS_KERNEL_VERSION)
> return THIS_KERNEL_VERSION;
>
> - string = pc->read_vmcoreinfo("OSRELEASE");
> - if (string) {
> - strcpy(buf, string);
> -
> - p1 = p2 = buf;
> - while (*p2 != '.')
> - p2++;
> - *p2 = NULLCHAR;
> - kt->kernel_version[0] = atoi(p1);
> -
> - p1 = ++p2;
> - while (*p2 != '.')
> - p2++;
> - *p2 = NULLCHAR;
> - kt->kernel_version[1] = atoi(p1);
> -
> - p1 = ++p2;
> - while ((*p2 >= '0') && (*p2 <= '9'))
> - p2++;
> - *p2 = NULLCHAR;
> - kt->kernel_version[2] = atoi(p1);
> + if ((string = pc->read_vmcoreinfo("OSRELEASE"))) {
> + parse_kernel_version(string);
> free(string);
> }
> return THIS_KERNEL_VERSION;
> --
> 2.41.0
>
1 year, 3 months
[Crash-utility PATCH] RISCV64: Add KASLR support
by Song Shuai
From: Song Shuai <suagrfillet(a)gmail.com>
This patch adds KASLR support for Crash to analyze KASLR-ed vmcore
since RISC-V Linux is already sufficiently prepared for KASLR [1].
With this patch, even if the Crash '--kaslr' option is not set or Linux
CONFIG_RANDOMIZE_BASE is not configured, the 'derive_kaslr_offset()'
function will always work to calculate 'kt->relocate' which serves to
update the kernel virtual address.
[1]: https://lore.kernel.org/linux-riscv/20230722123850.634544-1-alexghiti@riv...
Signed-off-by: Song Shuai <suagrfillet(a)gmail.com>
---
main.c | 2 +-
riscv64.c | 11 +++++++++++
symbols.c | 4 ++--
3 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/main.c b/main.c
index b278c22..0c6e595 100644
--- a/main.c
+++ b/main.c
@@ -228,7 +228,7 @@ main(int argc, char **argv)
} else if (STREQ(long_options[option_index].name, "kaslr")) {
if (!machine_type("X86_64") &&
!machine_type("ARM64") && !machine_type("X86") &&
- !machine_type("S390X"))
+ !machine_type("S390X") && !machine_type("RISCV64"))
error(INFO, "--kaslr not valid "
"with this machine type.\n");
else if (STREQ(optarg, "auto"))
diff --git a/riscv64.c b/riscv64.c
index a02f75a..288c7ae 100644
--- a/riscv64.c
+++ b/riscv64.c
@@ -378,6 +378,9 @@ static void riscv64_get_va_range(struct machine_specific *ms)
} else
goto error;
+ if ((kt->flags2 & KASLR) && (kt->flags & RELOC_SET))
+ ms->kernel_link_addr += (kt->relocate * -1);
+
/*
* From Linux 5.13, the kernel mapping is moved to the last 2GB
* of the address space, modules use the 2GB memory range right
@@ -1360,6 +1363,14 @@ riscv64_init(int when)
machdep->verify_paddr = generic_verify_paddr;
machdep->ptrs_per_pgd = PTRS_PER_PGD;
+
+ /*
+ * Even if CONFIG_RANDOMIZE_BASE is not configured,
+ * derive_kaslr_offset() should work and set
+ * kt->relocate to 0
+ */
+ if (!kt->relocate && !(kt->flags2 & (RELOC_AUTO|KASLR)))
+ kt->flags2 |= (RELOC_AUTO|KASLR);
break;
case PRE_GDB:
diff --git a/symbols.c b/symbols.c
index 876be7a..8e8b4c3 100644
--- a/symbols.c
+++ b/symbols.c
@@ -629,7 +629,7 @@ kaslr_init(void)
char *string;
if ((!machine_type("X86_64") && !machine_type("ARM64") && !machine_type("X86") &&
- !machine_type("S390X")) || (kt->flags & RELOC_SET))
+ !machine_type("S390X") && !machine_type("RISCV64")) || (kt->flags & RELOC_SET))
return;
if (!kt->vmcoreinfo._stext_SYMBOL &&
@@ -795,7 +795,7 @@ store_symbols(bfd *abfd, int dynamic, void *minisyms, long symcount,
} else if (!(kt->flags & RELOC_SET))
kt->flags |= RELOC_FORCE;
} else if (machine_type("X86_64") || machine_type("ARM64") ||
- machine_type("S390X")) {
+ machine_type("S390X") || machine_type("RISCV64")) {
if ((kt->flags2 & RELOC_AUTO) && !(kt->flags & RELOC_SET))
derive_kaslr_offset(abfd, dynamic, from,
fromend, size, store);
--
2.20.1
1 year, 3 months
[PATCH] deduplicate kernel_version open-coded parser
by Rafael Aquini
The code that parses kernel version from OSRELEASE/UTSRELEASE strings
and populates the global kernel table is duplicated across the codebase
for no good reason. This commit consolidates all the duplicated parsing
code into a single method to remove the unnecessary duplicated code.
Signed-off-by: Rafael Aquini <aquini(a)redhat.com>
---
arm64.c | 27 +++----------------
defs.h | 2 ++
kernel.c | 77 ++++++++++++++++++++++++++-----------------------------
riscv64.c | 25 ++----------------
4 files changed, 43 insertions(+), 88 deletions(-)
diff --git a/arm64.c b/arm64.c
index 67b1a22..39d5f04 100644
--- a/arm64.c
+++ b/arm64.c
@@ -834,35 +834,14 @@ static struct kernel_va_range_handler kernel_va_range_handlers[] = {
static unsigned long arm64_get_kernel_version(void)
{
char *string;
- char buf[BUFSIZE];
- char *p1, *p2;
if (THIS_KERNEL_VERSION)
return THIS_KERNEL_VERSION;
- string = pc->read_vmcoreinfo("OSRELEASE");
- if (string) {
- strcpy(buf, string);
-
- p1 = p2 = buf;
- while (*p2 != '.')
- p2++;
- *p2 = NULLCHAR;
- kt->kernel_version[0] = atoi(p1);
-
- p1 = ++p2;
- while (*p2 != '.')
- p2++;
- *p2 = NULLCHAR;
- kt->kernel_version[1] = atoi(p1);
-
- p1 = ++p2;
- while ((*p2 >= '0') && (*p2 <= '9'))
- p2++;
- *p2 = NULLCHAR;
- kt->kernel_version[2] = atoi(p1);
+ if ((string = pc->read_vmcoreinfo("OSRELEASE"))) {
+ parse_kernel_version(string);
+ free(string);
}
- free(string);
return THIS_KERNEL_VERSION;
}
diff --git a/defs.h b/defs.h
index 5ee60f1..1925148 100644
--- a/defs.h
+++ b/defs.h
@@ -6032,6 +6032,8 @@ void clone_bt_info(struct bt_info *, struct bt_info *, struct task_context *);
void dump_kernel_table(int);
void dump_bt_info(struct bt_info *, char *where);
void dump_log(int);
+void parse_kernel_version(char *);
+
#define LOG_LEVEL(v) ((v) & 0x07)
#define SHOW_LOG_LEVEL (0x1)
#define SHOW_LOG_DICT (0x2)
diff --git a/kernel.c b/kernel.c
index 2114700..988206b 100644
--- a/kernel.c
+++ b/kernel.c
@@ -104,6 +104,38 @@ static void check_vmcoreinfo(void);
static int is_pvops_xen(void);
static int get_linux_banner_from_vmlinux(char *, size_t);
+/*
+ * popuplate the global kernel table (kt) with kernel version
+ * information parsed from UTSNAME/OSRELEASE string
+ */
+void
+parse_kernel_version(char *str)
+{
+ char *p1, *p2, separator;
+
+ p1 = p2 = str;
+ while (*p2 != '.' && *p2 != '\0')
+ p2++;
+
+ *p2 = NULLCHAR;
+ kt->kernel_version[0] = atoi(p1);
+ p1 = ++p2;
+ while (*p2 != '.' && *p2 != '-' && *p2 != '\0')
+ p2++;
+
+ separator = *p2;
+ *p2 = NULLCHAR;
+ kt->kernel_version[1] = atoi(p1);
+
+ if (separator == '.') {
+ p1 = ++p2;
+ while ((*p2 >= '0') && (*p2 <= '9'))
+ p2++;
+
+ *p2 = NULLCHAR;
+ kt->kernel_version[2] = atoi(p1);
+ }
+}
/*
* Gather a few kernel basics.
@@ -112,7 +144,7 @@ void
kernel_init()
{
int i, c;
- char *p1, *p2, buf[BUFSIZE];
+ char buf[BUFSIZE];
struct syment *sp1, *sp2;
char *rqstruct;
char *rq_timestamp_name = NULL;
@@ -270,28 +302,7 @@ kernel_init()
if (buf[64])
buf[64] = NULLCHAR;
if (ascii_string(kt->utsname.release)) {
- char separator;
-
- p1 = p2 = buf;
- while (*p2 != '.')
- p2++;
- *p2 = NULLCHAR;
- kt->kernel_version[0] = atoi(p1);
- p1 = ++p2;
- while (*p2 != '.' && *p2 != '-' && *p2 != '\0')
- p2++;
- separator = *p2;
- *p2 = NULLCHAR;
- kt->kernel_version[1] = atoi(p1);
- *p2 = separator;
- if (*p2 == '.') {
- p1 = ++p2;
- while ((*p2 >= '0') && (*p2 <= '9'))
- p2++;
- *p2 = NULLCHAR;
- kt->kernel_version[2] = atoi(p1);
- } else
- kt->kernel_version[2] = 0;
+ parse_kernel_version(buf);
if (CRASHDEBUG(1))
fprintf(fp, "base kernel version: %d.%d.%d\n",
@@ -10973,8 +10984,6 @@ void
get_log_from_vmcoreinfo(char *file)
{
char *string;
- char buf[BUFSIZE];
- char *p1, *p2;
struct vmcoreinfo_data *vmc = &kt->vmcoreinfo;
if (!(pc->flags2 & VMCOREINFO))
@@ -10986,22 +10995,8 @@ get_log_from_vmcoreinfo(char *file)
if ((string = pc->read_vmcoreinfo("OSRELEASE"))) {
if (CRASHDEBUG(1))
fprintf(fp, "OSRELEASE: %s\n", string);
- strcpy(buf, string);
- p1 = p2 = buf;
- while (*p2 != '.')
- p2++;
- *p2 = NULLCHAR;
- kt->kernel_version[0] = atoi(p1);
- p1 = ++p2;
- while (*p2 != '.')
- p2++;
- *p2 = NULLCHAR;
- kt->kernel_version[1] = atoi(p1);
- p1 = ++p2;
- while ((*p2 >= '0') && (*p2 <= '9'))
- p2++;
- *p2 = NULLCHAR;
- kt->kernel_version[2] = atoi(p1);
+
+ parse_kernel_version(string);
if (CRASHDEBUG(1))
fprintf(fp, "base kernel version: %d.%d.%d\n",
diff --git a/riscv64.c b/riscv64.c
index 6b9a688..066cf2c 100644
--- a/riscv64.c
+++ b/riscv64.c
@@ -259,33 +259,12 @@ riscv64_processor_speed(void)
static unsigned long riscv64_get_kernel_version(void)
{
char *string;
- char buf[BUFSIZE];
- char *p1, *p2;
if (THIS_KERNEL_VERSION)
return THIS_KERNEL_VERSION;
- string = pc->read_vmcoreinfo("OSRELEASE");
- if (string) {
- strcpy(buf, string);
-
- p1 = p2 = buf;
- while (*p2 != '.')
- p2++;
- *p2 = NULLCHAR;
- kt->kernel_version[0] = atoi(p1);
-
- p1 = ++p2;
- while (*p2 != '.')
- p2++;
- *p2 = NULLCHAR;
- kt->kernel_version[1] = atoi(p1);
-
- p1 = ++p2;
- while ((*p2 >= '0') && (*p2 <= '9'))
- p2++;
- *p2 = NULLCHAR;
- kt->kernel_version[2] = atoi(p1);
+ if ((string = pc->read_vmcoreinfo("OSRELEASE"))) {
+ parse_kernel_version(string);
free(string);
}
return THIS_KERNEL_VERSION;
--
2.41.0
1 year, 3 months
[PATCH 1/2] Revert "Fix "kmem -s|-S" not working properly on RHEL8.6 and later"
by Lianbo Jiang
This reverts commit 9253b40a0ecb2d365f89f0a5ebc28a01735c1d24.
The commit 9253b40a0ecb only handles the current issue on X86 64/X86
architectures, furthermore the freelist_ptr_bswap_x86() depends on
disassembling a static symbol which might not be available, depending on
how the compiler decides to optimize the code, that is to say, the
compiler might generate different code eventually.
More importantly, a subsequent patch can cover the current issue on
various architectures. Given that, revert the commit.
Signed-off-by: Lianbo Jiang <lijiang(a)redhat.com>
---
defs.h | 1 -
memory.c | 49 +------------------------------------------------
2 files changed, 1 insertion(+), 49 deletions(-)
diff --git a/defs.h b/defs.h
index 5ee60f1eb3a5..b7d2382cb314 100644
--- a/defs.h
+++ b/defs.h
@@ -2662,7 +2662,6 @@ struct vm_table { /* kernel VM-related data */
#define SLAB_OVERLOAD_PAGE (0x8000000)
#define SLAB_CPU_CACHE (0x10000000)
#define SLAB_ROOT_CACHES (0x20000000)
-#define FREELIST_PTR_BSWAP (0x40000000)
#define IS_FLATMEM() (vt->flags & FLATMEM)
#define IS_DISCONTIGMEM() (vt->flags & DISCONTIGMEM)
diff --git a/memory.c b/memory.c
index acbee6389472..626c6039c6d9 100644
--- a/memory.c
+++ b/memory.c
@@ -320,7 +320,6 @@ static void dump_per_cpu_offsets(void);
static void dump_page_flags(ulonglong);
static ulong kmem_cache_nodelists(ulong);
static void dump_hstates(void);
-static void freelist_ptr_init(void);
static ulong freelist_ptr(struct meminfo *, ulong, ulong);
static ulong handle_each_vm_area(struct handle_each_vm_area_args *);
@@ -791,8 +790,6 @@ vm_init(void)
MEMBER_OFFSET_INIT(kmem_cache_name, "kmem_cache", "name");
MEMBER_OFFSET_INIT(kmem_cache_flags, "kmem_cache", "flags");
MEMBER_OFFSET_INIT(kmem_cache_random, "kmem_cache", "random");
- if (VALID_MEMBER(kmem_cache_random))
- freelist_ptr_init();
MEMBER_OFFSET_INIT(kmem_cache_cpu_freelist, "kmem_cache_cpu", "freelist");
MEMBER_OFFSET_INIT(kmem_cache_cpu_page, "kmem_cache_cpu", "page");
if (INVALID_MEMBER(kmem_cache_cpu_page))
@@ -13965,8 +13962,6 @@ dump_vm_table(int verbose)
fprintf(fp, "%sSLAB_CPU_CACHE", others++ ? "|" : "");\
if (vt->flags & SLAB_ROOT_CACHES)
fprintf(fp, "%sSLAB_ROOT_CACHES", others++ ? "|" : "");\
- if (vt->flags & FREELIST_PTR_BSWAP)
- fprintf(fp, "%sFREELIST_PTR_BSWAP", others++ ? "|" : "");\
if (vt->flags & USE_VMAP_AREA)
fprintf(fp, "%sUSE_VMAP_AREA", others++ ? "|" : "");\
if (vt->flags & CONFIG_NUMA)
@@ -19653,55 +19648,13 @@ count_free_objects(struct meminfo *si, ulong freelist)
return c;
}
-/*
- * With CONFIG_SLAB_FREELIST_HARDENED, freelist_ptr's are crypted with xor's,
- * and for recent release with an additionnal bswap. Some releases prio to 5.7.0
- * may be using the additionnal bswap. The only easy and reliable way to tell is
- * to inspect assembly code (eg. "__slab_free") for a bswap instruction.
- */
-static int
-freelist_ptr_bswap_x86(void)
-{
- char buf1[BUFSIZE];
- char buf2[BUFSIZE];
- char *arglist[MAXARGS];
- int found;
-
- sprintf(buf1, "disassemble __slab_free");
- open_tmpfile();
- if (!gdb_pass_through(buf1, pc->tmpfile, GNU_RETURN_ON_ERROR)) {
- close_tmpfile();
- return FALSE;
- }
- rewind(pc->tmpfile);
- found = FALSE;
- while (fgets(buf2, BUFSIZE, pc->tmpfile)) {
- if (parse_line(buf2, arglist) < 3)
- continue;
- if (STREQ(arglist[2], "bswap")) {
- found = TRUE;
- break;
- }
- }
- close_tmpfile();
- return found;
-}
-
-static void
-freelist_ptr_init(void)
-{
- if (THIS_KERNEL_VERSION >= LINUX(5,7,0) ||
- ((machine_type("X86_64") || machine_type("X86")) && freelist_ptr_bswap_x86()))
- vt->flags |= FREELIST_PTR_BSWAP;
-}
-
static ulong
freelist_ptr(struct meminfo *si, ulong ptr, ulong ptr_addr)
{
if (VALID_MEMBER(kmem_cache_random)) {
/* CONFIG_SLAB_FREELIST_HARDENED */
- if (vt->flags & FREELIST_PTR_BSWAP)
+ if (THIS_KERNEL_VERSION >= LINUX(5,7,0))
ptr_addr = (sizeof(long) == 8) ? bswap_64(ptr_addr)
: bswap_32(ptr_addr);
return (ptr ^ si->random ^ ptr_addr);
--
2.37.1
1 year, 3 months
Re: [Crash-utility] [PATCH V2] RISCV64: Use va_kernel_pa_offset in VTOP()
by lijiang
Thank you for the update, Song.
On Mon, Aug 14, 2023 at 9:54 AM <crash-utility-request(a)redhat.com> wrote:
> Date: Fri, 4 Aug 2023 17:15:59 +0800
> From: Song Shuai <suagrfillet(a)gmail.com>
> To: xianting.tian(a)linux.alibaba.com, mick(a)ics.forth.gr,
> heinrich.schuchardt(a)canonical.com, guoren(a)kernel.org,
> k-hagio-ab(a)nec.com, yixun.lan(a)gmail.com, lijiang(a)redhat.com
> Cc: linux-riscv(a)lists.infradead.org, kexec(a)lists.infradead.org,
> crash-utility(a)redhat.com, Song Shuai <suagrfillet(a)gmail.com>
> Subject: [Crash-utility] [Crash-utility PATCH V2] RISCV64: Use
> va_kernel_pa_offset in VTOP()
> Message-ID: <20230804091559.3005820-1-suagrfillet(a)gmail.com>
> Content-Type: text/plain; charset="US-ASCII"; x-default=true
>
> Since RISC-V Linux v6.4, the commit 3335068f8721 ("riscv: Use
> PUD/P4D/PGD pages for the linear mapping") changes phys_ram_base from
> the physical start of the kernel to the actual start of the DRAM.
>
> The Crash's VTOP() still uses phys_ram_base and kernel_map.virt_addr
> to translate kernel virtual address, that made Crash boot failed with
> Linux v6.4 and later version.
>
> Let Linux export kernel_map.va_kernel_pa_offset in v6.5 and backported
> v6.4.0 stable, so Crash can use "va_kernel_pa_offset" to translate the
> kernel virtual address in VTOP() correctly.
>
> Signed-off-by: Song Shuai <suagrfillet(a)gmail.com>
> ---
> Changes since V1:
> - remove unnecessary first kernel version check as Kazu suggested
> - amend the commit-msg as Alex suggested
> ---
> defs.h | 4 ++--
> riscv64.c | 23 +++++++++++++++++++++++
> 2 files changed, 25 insertions(+), 2 deletions(-)
>
> diff --git a/defs.h b/defs.h
> index 5ee60f1..c07e6d7 100644
> --- a/defs.h
> +++ b/defs.h
> @@ -3662,8 +3662,7 @@ typedef signed int s32;
> ulong _X = X;
> \
> (THIS_KERNEL_VERSION >= LINUX(5,13,0) &&
> \
> (_X) >= machdep->machspec->kernel_link_addr) ?
> \
> - (((unsigned
> long)(_X)-(machdep->machspec->kernel_link_addr)) + \
> - machdep->machspec->phys_base):
> \
> + ((unsigned
> long)(_X)-(machdep->machspec->va_kernel_pa_offset)): \
> (((unsigned long)(_X)-(machdep->kvbase)) +
> \
> machdep->machspec->phys_base);
> \
> })
> @@ -7021,6 +7020,7 @@ struct machine_specific {
> ulong modules_vaddr;
> ulong modules_end;
> ulong kernel_link_addr;
> + ulong va_kernel_pa_offset;
>
> ulong _page_present;
> ulong _page_read;
> diff --git a/riscv64.c b/riscv64.c
> index 6b9a688..7b5dd3d 100644
> --- a/riscv64.c
> +++ b/riscv64.c
> @@ -418,6 +418,28 @@ error:
> error(FATAL, "cannot get vm layout\n");
> }
>
> +static void
> +riscv64_get_va_kernel_pa_offset(struct machine_specific *ms)
> +{
> + unsigned long kernel_version = riscv64_get_kernel_version();
> +
> + /*
> + * Since Linux v6.4 phys_base is not the physical start of the
> kernel,
> + * trying to use "va_kernel_pa_offset" to determine the offset
> between
> + * kernel virtual and physical addresses.
> + */
> + if (kernel_version >= LINUX(6,4,0)) {
>
Is it possible to detect the existence of the symbol
'linear_mapping_va_to_pa' or 'linear_mapping_pa_to_va' to decide reading
the value of 'va_kernel_pa_offset'? For example:
kernel_symbol_exists()/symbol_exists()
if (kernel_symbol_exists("linear_mapping_va_to_pa") ||
kernel_symbol_exists("linear_mapping_pa_to_va")) {
string = pc->read_vmcoreinfo("NUMBER(va_kernel_pa_offset)");
...
}
I saw the commit 3335068f8721 exported two symbols:
+phys_addr_t linear_mapping_va_to_pa(unsigned long x)
+{
+ BUG_ON(!kernel_map.va_pa_offset);
+
+ return ((unsigned long)(x) - kernel_map.va_pa_offset);
+}
+EXPORT_SYMBOL(linear_mapping_va_to_pa);
+
+void *linear_mapping_pa_to_va(unsigned long x)
+{
+ BUG_ON(!kernel_map.va_pa_offset);
+
+ return ((void *)((unsigned long)(x) + kernel_map.va_pa_offset));
+}
+EXPORT_SYMBOL(linear_mapping_pa_to_va);
Thanks.
Lianbo
+ char *string;
> + if ((string =
> pc->read_vmcoreinfo("NUMBER(va_kernel_pa_offset)"))) {
> + ms->va_kernel_pa_offset = htol(string, QUIET,
> NULL);
> + free(string);
> + } else
> + error(FATAL, "cannot read va_kernel_pa_offset\n");
> + }
> + else
> + ms->va_kernel_pa_offset = ms->kernel_link_addr -
> ms->phys_base;
> +}
> +
> static int
> riscv64_is_kvaddr(ulong vaddr)
> {
> @@ -1352,6 +1374,7 @@ riscv64_init(int when)
> riscv64_get_struct_page_size(machdep->machspec);
> riscv64_get_va_bits(machdep->machspec);
> riscv64_get_va_range(machdep->machspec);
> + riscv64_get_va_kernel_pa_offset(machdep->machspec);
>
> pt_level_alloc(&machdep->pgd, "cannot malloc pgd space.");
> pt_level_alloc(&machdep->machspec->p4d, "cannot malloc p4d
> space.");
> --
> 2.20.1
>
1 year, 3 months
[PATCH] Fix "ps/vm" commands to display correct memory usage
by Lianbo Jiang
Kernel commit eca56ff906bd ("mm, shmem: add internal shmem resident
memory accounting"), which adds internal shmem resident memory
accounting, and tallies into the mm_rss_stat counter.
As a result, the "ps/vm" commands fail to show correct memory usage when
a process uses an anonymous shared memory region.
Without the patch:
crash> ps 2150
PID PPID CPU TASK ST %MEM VSZ RSS COMM
2150 2105 14 ffff8fba86d74d40 IN 0.0 10488392 444 mmap_test
^^^
Currently, the "ps/vm" commands missed the shmem pages count, let's
count the shmem pages together with regular files and anonymous pages.
With the patch:
crash> ps 2150
PID PPID CPU TASK ST %MEM VSZ RSS COMM
2150 2105 14 ffff8fba86d74d40 IN 20.8 10488392 3659008 mmap_test
Reported-by: Buland Kumar Singh <bsingh(a)redhat.com>
Signed-off-by: Lianbo Jiang <lijiang(a)redhat.com>
---
defs.h | 1 +
memory.c | 59 ++++++++++++++++++++++++++++++++++++++++++--------------
task.c | 1 +
3 files changed, 46 insertions(+), 15 deletions(-)
diff --git a/defs.h b/defs.h
index 5ee60f1eb3a5..f784d40c0b17 100644
--- a/defs.h
+++ b/defs.h
@@ -887,6 +887,7 @@ struct task_table { /* kernel/local task table data */
int callbacks;
struct task_context **context_by_task; /* task_context sorted by task addr */
ulong pid_xarray;
+ long shmempages;
};
#define TASK_INIT_DONE (0x1)
diff --git a/memory.c b/memory.c
index acbee6389472..df85b69963b6 100644
--- a/memory.c
+++ b/memory.c
@@ -4466,13 +4466,13 @@ in_user_stack(ulong task, ulong vaddr)
}
/*
- * Set the const value of filepages and anonpages
- * according to MM_FILEPAGES and MM_ANONPAGES.
+ * Set the const value of filepages, anonpages and shmempages
+ * according to MM_FILEPAGES, MM_ANONPAGES and MM_SHMEMPAGES.
*/
static void
rss_page_types_init(void)
{
- long anonpages, filepages;
+ long anonpages, filepages, shmempages;
if (VALID_MEMBER(mm_struct_rss))
return;
@@ -4487,6 +4487,15 @@ rss_page_types_init(void)
}
tt->filepages = filepages;
tt->anonpages = anonpages;
+
+ /*
+ * The default value(MM_SHMEMPAGES) is 3, which is introduced
+ * in linux v4.5-rc1 and later. See commit eca56ff906bd.
+ */
+ if (!enumerator_value("MM_SHMEMPAGES", &shmempages))
+ tt->shmempages = -1;
+ else
+ tt->shmempages = shmempages;
}
}
@@ -4812,10 +4821,11 @@ get_task_mem_usage(ulong task, struct task_mem_usage *tm)
* Latest kernels have mm_struct.mm_rss_stat[].
*/
if (VALID_MEMBER(mm_struct_rss_stat) && VALID_MEMBER(mm_rss_stat_count)) {
- long anonpages, filepages, count;
+ long anonpages, filepages, shmempages, count;
anonpages = tt->anonpages;
filepages = tt->filepages;
+ shmempages = tt->shmempages;
count = LONG(tt->mm_struct +
OFFSET(mm_struct_rss_stat) +
OFFSET(mm_rss_stat_count) +
@@ -4836,6 +4846,15 @@ get_task_mem_usage(ulong task, struct task_mem_usage *tm)
if (count > 0)
rss += count;
+ if (shmempages > 0) {
+ count = LONG(tt->mm_struct +
+ OFFSET(mm_struct_rss_stat) +
+ OFFSET(mm_rss_stat_count) +
+ (shmempages * sizeof(long)));
+ if (count > 0)
+ rss += count;
+ }
+
} else if (VALID_MEMBER(mm_struct_rss_stat)) {
/* 6.2: struct percpu_counter rss_stat[NR_MM_COUNTERS] */
ulong fbc;
@@ -4847,6 +4866,10 @@ get_task_mem_usage(ulong task, struct task_mem_usage *tm)
fbc = tc->mm_struct + OFFSET(mm_struct_rss_stat) +
(tt->anonpages * SIZE(percpu_counter));
rss += percpu_counter_sum_positive(fbc);
+
+ fbc = tc->mm_struct + OFFSET(mm_struct_rss_stat) +
+ (tt->shmempages * SIZE(percpu_counter));
+ rss += percpu_counter_sum_positive(fbc);
}
/* Check whether SPLIT_RSS_COUNTING is enabled */
@@ -4880,12 +4903,11 @@ get_task_mem_usage(ulong task, struct task_mem_usage *tm)
if (ACTIVE() || last->rss_cache == UNINITIALIZED) {
while (first <= last)
{
+ ulong addr = first->task + OFFSET(task_struct_rss_stat) +
+ OFFSET(task_rss_stat_count);
+
/* count 0 -> filepages */
- if (!readmem(first->task +
- OFFSET(task_struct_rss_stat) +
- OFFSET(task_rss_stat_count), KVADDR,
- &sync_rss,
- sizeof(int),
+ if (!readmem(addr, KVADDR, &sync_rss, sizeof(int),
"task_struct rss_stat MM_FILEPAGES",
RETURN_ON_ERROR))
continue;
@@ -4894,12 +4916,7 @@ get_task_mem_usage(ulong task, struct task_mem_usage *tm)
rss_cache += sync_rss;
/* count 1 -> anonpages */
- if (!readmem(first->task +
- OFFSET(task_struct_rss_stat) +
- OFFSET(task_rss_stat_count) +
- sizeof(int),
- KVADDR, &sync_rss,
- sizeof(int),
+ if (!readmem(addr + sizeof(int), KVADDR, &sync_rss, sizeof(int),
"task_struct rss_stat MM_ANONPAGES",
RETURN_ON_ERROR))
continue;
@@ -4907,6 +4924,18 @@ get_task_mem_usage(ulong task, struct task_mem_usage *tm)
if (sync_rss > 0)
rss_cache += sync_rss;
+ /* count 3 -> shmempages */
+ if (tt->shmempages > 0) {
+ if (!readmem(addr + tt->shmempages * sizeof(int), KVADDR,
+ &sync_rss, sizeof(int),
+ "task_struct rss_stat MM_SHMEMPAGES",
+ RETURN_ON_ERROR))
+ continue;
+
+ if (sync_rss > 0)
+ rss_cache += sync_rss;
+ }
+
if (first == last)
break;
first++;
diff --git a/task.c b/task.c
index c9206f50c679..4018a543b715 100644
--- a/task.c
+++ b/task.c
@@ -7873,6 +7873,7 @@ dump_task_table(int verbose)
fprintf(fp, " init_pid_ns: %lx\n", tt->init_pid_ns);
fprintf(fp, " filepages: %ld\n", tt->filepages);
fprintf(fp, " anonpages: %ld\n", tt->anonpages);
+ fprintf(fp, " shmempages: %ld\n", tt->shmempages);
fprintf(fp, " stack_end_magic: %lx\n", tt->stack_end_magic);
fprintf(fp, " pf_kthread: %lx ", tt->pf_kthread);
switch (tt->pf_kthread)
--
2.37.1
1 year, 3 months
[Crash-utility PATCH V2] RISCV64: Use va_kernel_pa_offset in VTOP()
by Song Shuai
Since RISC-V Linux v6.4, the commit 3335068f8721 ("riscv: Use
PUD/P4D/PGD pages for the linear mapping") changes phys_ram_base from
the physical start of the kernel to the actual start of the DRAM.
The Crash's VTOP() still uses phys_ram_base and kernel_map.virt_addr
to translate kernel virtual address, that made Crash boot failed with
Linux v6.4 and later version.
Let Linux export kernel_map.va_kernel_pa_offset in v6.5 and backported
v6.4.0 stable, so Crash can use "va_kernel_pa_offset" to translate the
kernel virtual address in VTOP() correctly.
Signed-off-by: Song Shuai <suagrfillet(a)gmail.com>
---
Changes since V1:
- remove unnecessary first kernel version check as Kazu suggested
- amend the commit-msg as Alex suggested
---
defs.h | 4 ++--
riscv64.c | 23 +++++++++++++++++++++++
2 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/defs.h b/defs.h
index 5ee60f1..c07e6d7 100644
--- a/defs.h
+++ b/defs.h
@@ -3662,8 +3662,7 @@ typedef signed int s32;
ulong _X = X; \
(THIS_KERNEL_VERSION >= LINUX(5,13,0) && \
(_X) >= machdep->machspec->kernel_link_addr) ? \
- (((unsigned long)(_X)-(machdep->machspec->kernel_link_addr)) + \
- machdep->machspec->phys_base): \
+ ((unsigned long)(_X)-(machdep->machspec->va_kernel_pa_offset)): \
(((unsigned long)(_X)-(machdep->kvbase)) + \
machdep->machspec->phys_base); \
})
@@ -7021,6 +7020,7 @@ struct machine_specific {
ulong modules_vaddr;
ulong modules_end;
ulong kernel_link_addr;
+ ulong va_kernel_pa_offset;
ulong _page_present;
ulong _page_read;
diff --git a/riscv64.c b/riscv64.c
index 6b9a688..7b5dd3d 100644
--- a/riscv64.c
+++ b/riscv64.c
@@ -418,6 +418,28 @@ error:
error(FATAL, "cannot get vm layout\n");
}
+static void
+riscv64_get_va_kernel_pa_offset(struct machine_specific *ms)
+{
+ unsigned long kernel_version = riscv64_get_kernel_version();
+
+ /*
+ * Since Linux v6.4 phys_base is not the physical start of the kernel,
+ * trying to use "va_kernel_pa_offset" to determine the offset between
+ * kernel virtual and physical addresses.
+ */
+ if (kernel_version >= LINUX(6,4,0)) {
+ char *string;
+ if ((string = pc->read_vmcoreinfo("NUMBER(va_kernel_pa_offset)"))) {
+ ms->va_kernel_pa_offset = htol(string, QUIET, NULL);
+ free(string);
+ } else
+ error(FATAL, "cannot read va_kernel_pa_offset\n");
+ }
+ else
+ ms->va_kernel_pa_offset = ms->kernel_link_addr - ms->phys_base;
+}
+
static int
riscv64_is_kvaddr(ulong vaddr)
{
@@ -1352,6 +1374,7 @@ riscv64_init(int when)
riscv64_get_struct_page_size(machdep->machspec);
riscv64_get_va_bits(machdep->machspec);
riscv64_get_va_range(machdep->machspec);
+ riscv64_get_va_kernel_pa_offset(machdep->machspec);
pt_level_alloc(&machdep->pgd, "cannot malloc pgd space.");
pt_level_alloc(&machdep->machspec->p4d, "cannot malloc p4d space.");
--
2.20.1
1 year, 3 months