All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kieran Bingham <kieran.bingham@linaro.org>
To: jan.kiszka@siemens.com, linux-kernel@vger.kernel.org
Cc: lee.jones@linaro.org, peter.griffin@linaro.org,
	maxime.coquelin@st.com,
	Kieran Bingham <kieran.bingham@linaro.org>
Subject: [PATCHv3 09/13] scripts/gdb: Add meminfo command
Date: Thu,  3 Mar 2016 11:41:03 +0000	[thread overview]
Message-ID: <1457005267-843-10-git-send-email-kieran.bingham@linaro.org> (raw)
In-Reply-To: <1457005267-843-1-git-send-email-kieran.bingham@linaro.org>

Provide an equivalent of /proc/meminfo which should be available from
core dumps, or crashed kernels. This should allow a debugger to identify
if memory pressures were applicable in the instance of their issue

Signed-off-by: Kieran Bingham <kieran.bingham@linaro.org>

---

Changes from v1:
 - Updated to use LX_ macros for constants
 - Utilise the LX_CONFIG() options for conditional printing
 - Fixed meminfo command on Jan's target .config
 - Added missing segments to meminfo command (HUGEPAGE, QUICKLIST)
 - Adjusted for new list_for_each_entry() function
 - Fixed up for !CONFIG_SWAP and !CONFIG_MMU targets (Tested STM32)

Changes from v2:
 - Reduce line size on output lines causing pep8 warnings
 - Remove crept in 'pass' statement
---
 scripts/gdb/linux/constants.py.in |  34 ++++++
 scripts/gdb/linux/proc.py         | 228 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 262 insertions(+)

diff --git a/scripts/gdb/linux/constants.py.in b/scripts/gdb/linux/constants.py.in
index 57213ad8cf75..66562a8242bd 100644
--- a/scripts/gdb/linux/constants.py.in
+++ b/scripts/gdb/linux/constants.py.in
@@ -12,8 +12,16 @@
  *
  */
 
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/thread_info.h>
+
 #include <linux/fs.h>
+#include <linux/swap.h>
 #include <linux/mount.h>
+#include <linux/huge_mm.h>
+#include <linux/vmalloc.h>
+
 
 /* We need to stringify expanded macros so that they can be parsed */
 
@@ -51,3 +59,29 @@ LX_VALUE(MNT_NOATIME)
 LX_VALUE(MNT_NODIRATIME)
 LX_VALUE(MNT_RELATIME)
 
+/* asm/page.h */
+LX_GDBPARSED(PAGE_SHIFT)
+
+/* asm/thread_info.h */
+LX_GDBPARSED(THREAD_SIZE)
+
+/* linux/vmalloc.h */
+LX_GDBPARSED(VMALLOC_TOTAL)
+
+/* linux/swap.h */
+LX_GDBPARSED(MAX_SWAPFILES)
+
+
+/* Kernel Configs */
+LX_CONFIG(CONFIG_HIGHMEM)
+LX_CONFIG(CONFIG_MEMORY_FAILURE)
+LX_CONFIG(CONFIG_TRANSPARENT_HUGEPAGE)
+LX_CONFIG(CONFIG_CMA)
+LX_CONFIG(CONFIG_MMU)
+LX_CONFIG(CONFIG_SWAP)
+
+#ifndef CONFIG_NR_QUICK
+#define CONFIG_NR_QUICK 0
+#endif
+LX_VALUE(CONFIG_NR_QUICK)
+LX_CONFIG(CONFIG_QUICKLIST)
diff --git a/scripts/gdb/linux/proc.py b/scripts/gdb/linux/proc.py
index 115f20b07a54..e5a8dbe3aa3a 100644
--- a/scripts/gdb/linux/proc.py
+++ b/scripts/gdb/linux/proc.py
@@ -195,3 +195,231 @@ values of that process namespace"""
                         info_opts(MNT_INFO, m_flags)))
 
 LxMounts()
+
+
+bdev_type = utils.CachedType("struct block_device")
+bdev_ptr_type = bdev_type.get_type().pointer()
+
+
+class LxMeminfo(gdb.Command):
+    """ Identify the memory usage, statistics, and availability
+
+Equivalent to cat /proc/meminfo on a running target """
+
+    def __init__(self):
+        super(LxMeminfo, self).__init__("lx-meminfo", gdb.COMMAND_DATA)
+
+    def K(self, val):
+        # Convert from PAGES to KB
+        return int(val << (constants.LX_PAGE_SHIFT - 10))
+
+    def page_K(self, remote_value):
+        # Obtain page value, and Convert from PAGES to KB
+        val = int(gdb.parse_and_eval(remote_value))
+        return self.K(val)
+
+    def gps(self, enum_zone_stat_item):
+        # Access the Global Page State structure
+        # I would prefer to read this structure in one go and then index
+        # from the enum. But we can't determine the enum values with out
+        # a call to GDB anyway so we may as well take the easy route and
+        # get the value.
+        remote_value = "vm_stat[" + enum_zone_stat_item + "].counter"
+        return int(gdb.parse_and_eval(remote_value))
+
+    def gps_K(self, enum_zone_stat_item):
+        return self.K(self.gps(enum_zone_stat_item))
+
+    def nr_blockdev_pages(self):
+        bdevs_head = gdb.parse_and_eval("all_bdevs")
+        pages = 0
+        for bdev in lists.list_for_each_entry(bdevs_head,
+                                              bdev_ptr_type,
+                                              "bd_list"):
+            try:
+                pages += bdev['bd_inode']['i_mapping']['nrpages']
+            except:
+                # Any memory read failures are simply not counted
+                pass
+        return pages
+
+    def total_swapcache_pages(self):
+        pages = 0
+        if not constants.LX_CONFIG_SWAP:
+            return 0
+
+        for i in range(0, int(constants.LX_MAX_SWAPFILES)):
+            swap_space = "swapper_spaces[" + str(i) + "].nrpages"
+            pages += int(gdb.parse_and_eval(swap_space))
+        return pages
+
+    def vm_commit_limit(self, totalram_pages):
+        total_swap_pages = 0
+        overcommit = int(gdb.parse_and_eval("sysctl_overcommit_kbytes"))
+        overcommit_ratio = int(gdb.parse_and_eval("sysctl_overcommit_ratio"))
+
+        if constants.LX_CONFIG_SWAP:
+            total_swap_pages = int(gdb.parse_and_eval("total_swap_pages"))
+
+        hugetlb_total_pages = 0  # hugetlb_total_pages()
+
+        if overcommit:
+            allowed = overcommit >> (constants.LX_PAGE_SHIFT - 10)
+        else:
+            allowed = ((totalram_pages - hugetlb_total_pages *
+                       overcommit_ratio / 100))
+
+        allowed += total_swap_pages
+        return allowed
+
+    def quicklist_total_size(self):
+        count = 0
+        quicklist = utils.gdb_eval_or_none("quicklist")
+        if quicklist is None:
+            return 0
+
+        for cpu in cpus.each_online_cpu():
+            ql = cpus.per_cpu(quicklist, cpu)
+            for q in range(0, constants.LX_CONFIG_NR_QUICK):
+                # for (q = ql; q < ql + CONFIG_NR_QUICK; q++)
+                # count += q->nr_pages
+                count += ql[q]['nr_pages']
+
+        return count
+
+    # Main lx-meminfo command execution
+    # See fs/proc/meminfo.c:meminfo_proc_show()
+    def invoke(self, arg, from_tty):
+        totalram = int(gdb.parse_and_eval("totalram_pages"))
+        freeram = self.gps("NR_FREE_PAGES")
+        reclaimable = self.gps("NR_SLAB_RECLAIMABLE")
+        unreclaimable = self.gps("NR_SLAB_UNRECLAIMABLE")
+        slab = reclaimable + unreclaimable
+        # for_each_zone(zone)
+        #     wmark_low += zone->watermark[WMARK_LOW];
+        wmark_low = 0   # Zone parsing is unimplemented
+
+        available = freeram - wmark_low
+        available += reclaimable - min(reclaimable / 2, wmark_low)
+
+        bufferram = self.nr_blockdev_pages()
+        swapcached = self.total_swapcache_pages()
+
+        file_pages = self.gps("NR_FILE_PAGES")
+        cached = file_pages - swapcached - bufferram
+
+        # LRU Pages
+        active_pages_anon = self.gps("NR_ACTIVE_ANON")
+        inactive_pages_anon = self.gps("NR_INACTIVE_ANON")
+        active_pages_file = self.gps("NR_ACTIVE_FILE")
+        inactive_pages_file = self.gps("NR_INACTIVE_FILE")
+        unevictable_pages = self.gps("NR_UNEVICTABLE")
+        active_pages = active_pages_anon + active_pages_file
+        inactive_pages = inactive_pages_anon + inactive_pages_file
+
+        kernelstack = int(self.gps("NR_KERNEL_STACK") *
+                          constants.LX_THREAD_SIZE / 1024)
+
+        commitlimit = int(self.vm_commit_limit(totalram))
+        committed_as = int(gdb.parse_and_eval("vm_committed_as.count"))
+
+        vmalloc_total = int(constants.LX_VMALLOC_TOTAL >> 10)
+
+        gdb.write(
+            "MemTotal:       {:8d} kB\n".format(self.K(totalram)) +
+            "MemFree:        {:8d} kB\n".format(self.K(freeram)) +
+            "MemAvailable:   {:8d} kB\n".format(self.K(available)) +
+            "Buffers:        {:8d} kB\n".format(self.K(bufferram)) +
+            "Cached:         {:8d} kB\n".format(self.K(cached)) +
+            "SwapCached:     {:8d} kB\n".format(self.K(swapcached)) +
+            "Active:         {:8d} kB\n".format(self.K(active_pages)) +
+            "Inactive:       {:8d} kB\n".format(self.K(inactive_pages)) +
+            "Active(anon):   {:8d} kB\n".format(self.K(active_pages_anon)) +
+            "Inactive(anon): {:8d} kB\n".format(self.K(inactive_pages_anon)) +
+            "Active(file):   {:8d} kB\n".format(self.K(active_pages_file)) +
+            "Inactive(file): {:8d} kB\n".format(self.K(inactive_pages_file)) +
+            "Unevictable:    {:8d} kB\n".format(self.K(unevictable_pages)) +
+            "Mlocked:        {:8d} kB\n".format(self.gps_K("NR_MLOCK"))
+            )
+
+        if constants.LX_CONFIG_HIGHMEM:
+            totalhigh = int(gdb.parse_and_eval("totalhigh_pages"))
+            freehigh = int(gdb.parse_and_eval("nr_free_highpages()"))
+            lowtotal = totalram - totalhigh
+            lowfree = freeram - freehigh
+            gdb.write(
+                "HighTotal:      {:8d} kB\n".format(self.K(totalhigh)) +
+                "HighFree:       {:8d} kB\n".format(self.K(freehigh)) +
+                "LowTotal:       {:8d} kB\n".format(self.K(lowtotal)) +
+                "LowFree:        {:8d} kB\n".format(self.K(lowfree))
+                )
+
+        if not constants.LX_CONFIG_MMU:
+            mmap_pg_alloc = gdb.parse_and_eval("mmap_pages_allocated.counter")
+            gdb.write(
+                "MmapCopy:       {:8d} kB\n".format(self.K(mmap_pg_alloc))
+                )
+
+        gdb.write(
+            "SwapTotal:      {:8d} kB\n".format(self.K(0)) +
+            "SwapFree:       {:8d} kB\n".format(self.K(0)) +
+            "Dirty:          {:8d} kB\n".format(self.gps_K("NR_FILE_DIRTY")) +
+            "Writeback:      {:8d} kB\n".format(self.gps_K("NR_WRITEBACK")) +
+            "AnonPages:      {:8d} kB\n".format(self.gps_K("NR_ANON_PAGES")) +
+            "Mapped:         {:8d} kB\n".format(self.gps_K("NR_FILE_MAPPED")) +
+            "Shmem:          {:8d} kB\n".format(self.gps_K("NR_SHMEM")) +
+            "Slab:           {:8d} kB\n".format(self.K(slab)) +
+            "SReclaimable:   {:8d} kB\n".format(self.K(reclaimable)) +
+            "SUnreclaim:     {:8d} kB\n".format(self.K(unreclaimable)) +
+            "KernelStack:    {:8d} kB\n".format(kernelstack) +
+            "PageTables:     {:8d} kB\n".format(self.gps_K("NR_PAGETABLE"))
+            )
+
+        if constants.LX_CONFIG_QUICKLIST:
+            quicklist = self.quicklist_total_size()
+            gdb.write(
+               "Quicklists:     {:8d} kB\n".format(self.K(quicklist))
+            )
+
+        nfsunstable = self.gps("NR_UNSTABLE_NFS")
+        nr_bounce = self.gps("NR_BOUNCE")
+        writebacktmp = self.gps("NR_WRITEBACK_TEMP")
+        gdb.write(
+            "NFS_Unstable:   {:8d} kB\n".format(self.K(nfsunstable)) +
+            "Bounce:         {:8d} kB\n".format(self.K(nr_bounce)) +
+            "WritebackTmp:   {:8d} kB\n".format(self.K(writebacktmp))
+            )
+
+        gdb.write(
+            "CommitLimit:    {:8d} kB\n".format(self.K(commitlimit)) +
+            "Committed_AS:   {:8d} kB\n".format(self.K(committed_as)) +
+            "VmallocTotal:   {:8d} kB\n".format(vmalloc_total)
+            )
+
+        # These are always zero now
+        gdb.write(
+            "VmallocUsed:    {:8d} kB\n".format(0) +
+            "VmallocChunk:   {:8d} kB\n".format(0)
+            )
+
+        if constants.LX_CONFIG_MEMORY_FAILURE:
+            gdb.write(
+                "HardwareCorrupted: {:8d} kB\n"
+            )
+
+        if constants.LX_CONFIG_TRANSPARENT_HUGEPAGE:
+            huge = self.gps("NR_ANON_TRANSPARENT_HUGEPAGES")
+            # HPAGE_PMD_NR can not be determined in constants.py
+            gdb.write(
+                "AnonHugePages:  {:8d} kB ( * HPAGE_PMD_NR )\n"
+                .format(self.K(huge))
+            )
+        if constants.LX_CONFIG_CMA:
+            totalcma_pages = int(gdb.parse_and_eval("totalcma_pages"))
+            cmafree = self.gps("NR_FREE_CMA_PAGES")
+            gdb.write(
+                "CmaTotal:       {:8d} kB\n".format(self.K(totalcma_pages)) +
+                "CmaFree:        {:8d} kB\n".format(self.K(cmafree))
+            )
+
+LxMeminfo()
-- 
2.5.0

  parent reply	other threads:[~2016-03-03 11:44 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-03 11:40 [PATCHv3 00/13] scripts/gdb: Linux awareness debug commands Kieran Bingham
2016-03-03 11:40 ` [PATCHv3 01/13] scripts/gdb: Provide linux constants Kieran Bingham
2016-03-03 11:40 ` [PATCHv3 02/13] scripts/gdb: Provide kernel list item generators Kieran Bingham
2016-03-08  3:47   ` Jeff Mahoney
2016-03-08  7:55     ` Kieran Bingham
2016-03-03 11:40 ` [PATCHv3 03/13] scripts/gdb: Convert modules usage to lists functions Kieran Bingham
2016-03-03 11:40 ` [PATCHv3 04/13] scripts/gdb: Provide exception catching parser Kieran Bingham
2016-03-03 11:40 ` [PATCHv3 05/13] scripts/gdb: Support !CONFIG_MODULES gracefully Kieran Bingham
2016-03-03 11:41 ` [PATCHv3 06/13] scripts/gdb: Provide a dentry_name VFS path helper Kieran Bingham
2016-03-03 11:41 ` [PATCHv3 07/13] scripts/gdb: Add io resource readers Kieran Bingham
2016-03-03 11:41 ` [PATCHv3 08/13] scripts/gdb: Add mount point list command Kieran Bingham
2016-03-13 16:34   ` Jan Kiszka
2016-03-14 14:39     ` Kieran Bingham
2016-03-14 15:05       ` Jan Kiszka
2016-03-15 10:46         ` Kieran Bingham
2016-03-03 11:41 ` Kieran Bingham [this message]
2016-03-13 16:34   ` [PATCHv3 09/13] scripts/gdb: Add meminfo command Jan Kiszka
2016-03-13 18:16     ` Kieran Bingham
2016-03-13 19:08       ` Jan Kiszka
2016-03-14 12:13         ` Kieran Bingham
2016-03-03 11:41 ` [PATCHv3 10/13] scripts/gdb: Add cpu iterators Kieran Bingham
2016-03-13 16:33   ` Jan Kiszka
2016-03-13 18:39     ` Kieran Bingham
2016-03-03 11:41 ` [PATCHv3 11/13] scripts/gdb: Add a Radix Tree Parser Kieran Bingham
2016-03-03 11:41 ` [PATCHv3 12/13] scripts/gdb: Add interrupts command Kieran Bingham
2016-03-03 11:41 ` [PATCHv3 13/13] scripts/gdb: Add lx_thread_info_by_pid helper Kieran Bingham
2016-03-13 16:35 ` [PATCHv3 00/13] scripts/gdb: Linux awareness debug commands Jan Kiszka
2016-03-14 14:40   ` Kieran Bingham
2016-03-14 15:09     ` Jan Kiszka
2016-03-14 17:18       ` Kieran Bingham
2016-03-14 17:31         ` Jan Kiszka

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1457005267-843-10-git-send-email-kieran.bingham@linaro.org \
    --to=kieran.bingham@linaro.org \
    --cc=jan.kiszka@siemens.com \
    --cc=lee.jones@linaro.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=maxime.coquelin@st.com \
    --cc=peter.griffin@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.