ASR_BASE

Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/marvell/linux/scripts/gdb/Makefile b/marvell/linux/scripts/gdb/Makefile
new file mode 100644
index 0000000..3fca193
--- /dev/null
+++ b/marvell/linux/scripts/gdb/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+subdir-y := linux
diff --git a/marvell/linux/scripts/gdb/linux/.gitignore b/marvell/linux/scripts/gdb/linux/.gitignore
new file mode 100644
index 0000000..2573543
--- /dev/null
+++ b/marvell/linux/scripts/gdb/linux/.gitignore
@@ -0,0 +1,3 @@
+*.pyc
+*.pyo
+constants.py
diff --git a/marvell/linux/scripts/gdb/linux/Makefile b/marvell/linux/scripts/gdb/linux/Makefile
new file mode 100644
index 0000000..1247550
--- /dev/null
+++ b/marvell/linux/scripts/gdb/linux/Makefile
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: GPL-2.0
+
+ifdef building_out_of_srctree
+
+symlinks := $(patsubst $(srctree)/$(src)/%,%,$(wildcard $(srctree)/$(src)/*.py))
+
+quiet_cmd_symlink = SYMLINK $@
+      cmd_symlink = ln -fsn $(patsubst $(obj)/%,$(abspath $(srctree))/$(src)/%,$@) $@
+
+extra-y += $(symlinks)
+$(addprefix $(obj)/, $(symlinks)): FORCE
+	$(call if_changed,symlink)
+
+endif
+
+quiet_cmd_gen_constants_py = GEN     $@
+      cmd_gen_constants_py = \
+	$(CPP) -E -x c -P $(c_flags) $< > $@ ;\
+	sed -i '1,/<!-- end-c-headers -->/d;' $@
+
+extra-y += constants.py
+$(obj)/constants.py: $(src)/constants.py.in FORCE
+	$(call if_changed_dep,gen_constants_py)
+
+clean-files := *.pyc *.pyo
diff --git a/marvell/linux/scripts/gdb/linux/__init__.py b/marvell/linux/scripts/gdb/linux/__init__.py
new file mode 100644
index 0000000..4680fb1
--- /dev/null
+++ b/marvell/linux/scripts/gdb/linux/__init__.py
@@ -0,0 +1 @@
+# nothing to do for the initialization of this package
diff --git a/marvell/linux/scripts/gdb/linux/clk.py b/marvell/linux/scripts/gdb/linux/clk.py
new file mode 100644
index 0000000..7a01fdc
--- /dev/null
+++ b/marvell/linux/scripts/gdb/linux/clk.py
@@ -0,0 +1,78 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (c) NXP 2019
+
+import gdb
+import sys
+
+from linux import utils, lists, constants
+
+clk_core_type = utils.CachedType("struct clk_core")
+
+
+def clk_core_for_each_child(hlist_head):
+    return lists.hlist_for_each_entry(hlist_head,
+            clk_core_type.get_type().pointer(), "child_node")
+
+
+class LxClkSummary(gdb.Command):
+    """Print clk tree summary
+
+Output is a subset of /sys/kernel/debug/clk/clk_summary
+
+No calls are made during printing, instead a (c) if printed after values which
+are cached and potentially out of date"""
+
+    def __init__(self):
+        super(LxClkSummary, self).__init__("lx-clk-summary", gdb.COMMAND_DATA)
+
+    def show_subtree(self, clk, level):
+        gdb.write("%*s%-*s %7d %8d %8d %11lu%s\n" % (
+                level * 3 + 1, "",
+                30 - level * 3,
+                clk['name'].string(),
+                clk['enable_count'],
+                clk['prepare_count'],
+                clk['protect_count'],
+                clk['rate'],
+                '(c)' if clk['flags'] & constants.LX_CLK_GET_RATE_NOCACHE else '   '))
+
+        for child in clk_core_for_each_child(clk['children']):
+            self.show_subtree(child, level + 1)
+
+    def invoke(self, arg, from_tty):
+        if utils.gdb_eval_or_none("clk_root_list") is None:
+            raise gdb.GdbError("No clocks registered")
+        gdb.write("                                 enable  prepare  protect               \n")
+        gdb.write("   clock                          count    count    count        rate   \n")
+        gdb.write("------------------------------------------------------------------------\n")
+        for clk in clk_core_for_each_child(gdb.parse_and_eval("clk_root_list")):
+            self.show_subtree(clk, 0)
+        for clk in clk_core_for_each_child(gdb.parse_and_eval("clk_orphan_list")):
+            self.show_subtree(clk, 0)
+
+
+LxClkSummary()
+
+
+class LxClkCoreLookup(gdb.Function):
+    """Find struct clk_core by name"""
+
+    def __init__(self):
+        super(LxClkCoreLookup, self).__init__("lx_clk_core_lookup")
+
+    def lookup_hlist(self, hlist_head, name):
+        for child in clk_core_for_each_child(hlist_head):
+            if child['name'].string() == name:
+                return child
+            result = self.lookup_hlist(child['children'], name)
+            if result:
+                return result
+
+    def invoke(self, name):
+        name = name.string()
+        return (self.lookup_hlist(gdb.parse_and_eval("clk_root_list"), name) or
+                self.lookup_hlist(gdb.parse_and_eval("clk_orphan_list"), name))
+
+
+LxClkCoreLookup()
diff --git a/marvell/linux/scripts/gdb/linux/config.py b/marvell/linux/scripts/gdb/linux/config.py
new file mode 100644
index 0000000..8843ab3
--- /dev/null
+++ b/marvell/linux/scripts/gdb/linux/config.py
@@ -0,0 +1,44 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright 2019 Google LLC.
+
+import gdb
+import zlib
+
+from linux import utils
+
+
+class LxConfigDump(gdb.Command):
+    """Output kernel config to the filename specified as the command
+       argument. Equivalent to 'zcat /proc/config.gz > config.txt' on
+       a running target"""
+
+    def __init__(self):
+        super(LxConfigDump, self).__init__("lx-configdump", gdb.COMMAND_DATA,
+                                           gdb.COMPLETE_FILENAME)
+
+    def invoke(self, arg, from_tty):
+        if len(arg) == 0:
+            filename = "config.txt"
+        else:
+            filename = arg
+
+        try:
+            py_config_ptr = gdb.parse_and_eval("&kernel_config_data")
+            py_config_ptr_end = gdb.parse_and_eval("&kernel_config_data_end")
+            py_config_size = py_config_ptr_end - py_config_ptr
+        except gdb.error as e:
+            raise gdb.GdbError("Can't find config, enable CONFIG_IKCONFIG?")
+
+        inf = gdb.inferiors()[0]
+        zconfig_buf = utils.read_memoryview(inf, py_config_ptr,
+                                            py_config_size).tobytes()
+
+        config_buf = zlib.decompress(zconfig_buf, 16)
+        with open(filename, 'wb') as f:
+            f.write(config_buf)
+
+        gdb.write("Dumped config to " + filename + "\n")
+
+
+LxConfigDump()
diff --git a/marvell/linux/scripts/gdb/linux/constants.py.in b/marvell/linux/scripts/gdb/linux/constants.py.in
new file mode 100644
index 0000000..2efbec6
--- /dev/null
+++ b/marvell/linux/scripts/gdb/linux/constants.py.in
@@ -0,0 +1,77 @@
+/*
+ * gdb helper commands and functions for Linux kernel debugging
+ *
+ *  Kernel constants derived from include files.
+ *
+ * Copyright (c) 2016 Linaro Ltd
+ *
+ * Authors:
+ *  Kieran Bingham <kieran.bingham@linaro.org>
+ *
+ * This work is licensed under the terms of the GNU GPL version 2.
+ *
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/fs.h>
+#include <linux/hrtimer.h>
+#include <linux/mount.h>
+#include <linux/of_fdt.h>
+#include <linux/threads.h>
+
+/* We need to stringify expanded macros so that they can be parsed */
+
+#define STRING(x) #x
+#define XSTRING(x) STRING(x)
+
+#define LX_VALUE(x) LX_##x = x
+#define LX_GDBPARSED(x) LX_##x = gdb.parse_and_eval(XSTRING(x))
+
+/*
+ * IS_ENABLED generates (a || b) which is not compatible with python
+ * We can only switch on configuration items we know are available
+ * Therefore - IS_BUILTIN() is more appropriate
+ */
+#define LX_CONFIG(x) LX_##x = IS_BUILTIN(x)
+
+/* The build system will take care of deleting everything above this marker */
+<!-- end-c-headers -->
+
+import gdb
+
+/* linux/clk-provider.h */
+if IS_BUILTIN(CONFIG_COMMON_CLK):
+    LX_GDBPARSED(CLK_GET_RATE_NOCACHE)
+
+/* linux/fs.h */
+LX_VALUE(SB_RDONLY)
+LX_VALUE(SB_SYNCHRONOUS)
+LX_VALUE(SB_MANDLOCK)
+LX_VALUE(SB_DIRSYNC)
+LX_VALUE(SB_NOATIME)
+LX_VALUE(SB_NODIRATIME)
+
+/* linux/htimer.h */
+LX_GDBPARSED(hrtimer_resolution)
+
+/* linux/mount.h */
+LX_VALUE(MNT_NOSUID)
+LX_VALUE(MNT_NODEV)
+LX_VALUE(MNT_NOEXEC)
+LX_VALUE(MNT_NOATIME)
+LX_VALUE(MNT_NODIRATIME)
+LX_VALUE(MNT_RELATIME)
+
+/* linux/threads.h */
+LX_VALUE(NR_CPUS)
+
+/* linux/of_fdt.h> */
+LX_VALUE(OF_DT_HEADER)
+
+/* Kernel Configs */
+LX_CONFIG(CONFIG_GENERIC_CLOCKEVENTS)
+LX_CONFIG(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
+LX_CONFIG(CONFIG_HIGH_RES_TIMERS)
+LX_CONFIG(CONFIG_NR_CPUS)
+LX_CONFIG(CONFIG_OF)
+LX_CONFIG(CONFIG_TICK_ONESHOT)
diff --git a/marvell/linux/scripts/gdb/linux/cpus.py b/marvell/linux/scripts/gdb/linux/cpus.py
new file mode 100644
index 0000000..008e62f
--- /dev/null
+++ b/marvell/linux/scripts/gdb/linux/cpus.py
@@ -0,0 +1,174 @@
+#
+# gdb helper commands and functions for Linux kernel debugging
+#
+#  per-cpu tools
+#
+# Copyright (c) Siemens AG, 2011-2013
+#
+# Authors:
+#  Jan Kiszka <jan.kiszka@siemens.com>
+#
+# This work is licensed under the terms of the GNU GPL version 2.
+#
+
+import gdb
+
+from linux import tasks, utils
+
+
+MAX_CPUS = 4096
+
+
+def get_current_cpu():
+    if utils.get_gdbserver_type() == utils.GDBSERVER_QEMU:
+        return gdb.selected_thread().num - 1
+    elif utils.get_gdbserver_type() == utils.GDBSERVER_KGDB:
+        tid = gdb.selected_thread().ptid[2]
+        if tid > (0x100000000 - MAX_CPUS - 2):
+            return 0x100000000 - tid - 2
+        else:
+            return tasks.get_thread_info(tasks.get_task_by_pid(tid))['cpu']
+    else:
+        raise gdb.GdbError("Sorry, obtaining the current CPU is not yet "
+                           "supported with this gdb server.")
+
+
+def per_cpu(var_ptr, cpu):
+    if cpu == -1:
+        cpu = get_current_cpu()
+    if utils.is_target_arch("sparc:v9"):
+        offset = gdb.parse_and_eval(
+            "trap_block[{0}].__per_cpu_base".format(str(cpu)))
+    else:
+        try:
+            offset = gdb.parse_and_eval(
+                "__per_cpu_offset[{0}]".format(str(cpu)))
+        except gdb.error:
+            # !CONFIG_SMP case
+            offset = 0
+    pointer = var_ptr.cast(utils.get_long_type()) + offset
+    return pointer.cast(var_ptr.type).dereference()
+
+
+cpu_mask = {}
+
+
+def cpu_mask_invalidate(event):
+    global cpu_mask
+    cpu_mask = {}
+    gdb.events.stop.disconnect(cpu_mask_invalidate)
+    if hasattr(gdb.events, 'new_objfile'):
+        gdb.events.new_objfile.disconnect(cpu_mask_invalidate)
+
+
+def cpu_list(mask_name):
+    global cpu_mask
+    mask = None
+    if mask_name in cpu_mask:
+        mask = cpu_mask[mask_name]
+    if mask is None:
+        mask = gdb.parse_and_eval(mask_name + ".bits")
+        if hasattr(gdb, 'events'):
+            cpu_mask[mask_name] = mask
+            gdb.events.stop.connect(cpu_mask_invalidate)
+            if hasattr(gdb.events, 'new_objfile'):
+                gdb.events.new_objfile.connect(cpu_mask_invalidate)
+    bits_per_entry = mask[0].type.sizeof * 8
+    num_entries = mask.type.sizeof * 8 / bits_per_entry
+    entry = -1
+    bits = 0
+
+    while True:
+        while bits == 0:
+            entry += 1
+            if entry == num_entries:
+                return
+            bits = mask[entry]
+            if bits != 0:
+                bit = 0
+                break
+
+        while bits & 1 == 0:
+            bits >>= 1
+            bit += 1
+
+        cpu = entry * bits_per_entry + bit
+
+        bits >>= 1
+        bit += 1
+
+        yield int(cpu)
+
+
+def each_online_cpu():
+    for cpu in cpu_list("__cpu_online_mask"):
+        yield cpu
+
+
+def each_present_cpu():
+    for cpu in cpu_list("__cpu_present_mask"):
+        yield cpu
+
+
+def each_possible_cpu():
+    for cpu in cpu_list("__cpu_possible_mask"):
+        yield cpu
+
+
+def each_active_cpu():
+    for cpu in cpu_list("__cpu_active_mask"):
+        yield cpu
+
+
+class LxCpus(gdb.Command):
+    """List CPU status arrays
+
+Displays the known state of each CPU based on the kernel masks
+and can help identify the state of hotplugged CPUs"""
+
+    def __init__(self):
+        super(LxCpus, self).__init__("lx-cpus", gdb.COMMAND_DATA)
+
+    def invoke(self, arg, from_tty):
+        gdb.write("Possible CPUs : {}\n".format(list(each_possible_cpu())))
+        gdb.write("Present CPUs  : {}\n".format(list(each_present_cpu())))
+        gdb.write("Online CPUs   : {}\n".format(list(each_online_cpu())))
+        gdb.write("Active CPUs   : {}\n".format(list(each_active_cpu())))
+
+
+LxCpus()
+
+
+class PerCpu(gdb.Function):
+    """Return per-cpu variable.
+
+$lx_per_cpu("VAR"[, CPU]): Return the per-cpu variable called VAR for the
+given CPU number. If CPU is omitted, the CPU of the current context is used.
+Note that VAR has to be quoted as string."""
+
+    def __init__(self):
+        super(PerCpu, self).__init__("lx_per_cpu")
+
+    def invoke(self, var_name, cpu=-1):
+        var_ptr = gdb.parse_and_eval("&" + var_name.string())
+        return per_cpu(var_ptr, cpu)
+
+
+PerCpu()
+
+
+class LxCurrentFunc(gdb.Function):
+    """Return current task.
+
+$lx_current([CPU]): Return the per-cpu task variable for the given CPU
+number. If CPU is omitted, the CPU of the current context is used."""
+
+    def __init__(self):
+        super(LxCurrentFunc, self).__init__("lx_current")
+
+    def invoke(self, cpu=-1):
+        var_ptr = gdb.parse_and_eval("&current_task")
+        return per_cpu(var_ptr, cpu).dereference()
+
+
+LxCurrentFunc()
diff --git a/marvell/linux/scripts/gdb/linux/device.py b/marvell/linux/scripts/gdb/linux/device.py
new file mode 100644
index 0000000..16376c5
--- /dev/null
+++ b/marvell/linux/scripts/gdb/linux/device.py
@@ -0,0 +1,182 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (c) NXP 2019
+
+import gdb
+
+from linux.utils import CachedType
+from linux.utils import container_of
+from linux.lists import list_for_each_entry
+
+
+device_private_type = CachedType('struct device_private')
+device_type = CachedType('struct device')
+
+subsys_private_type = CachedType('struct subsys_private')
+kobject_type = CachedType('struct kobject')
+kset_type = CachedType('struct kset')
+
+bus_type = CachedType('struct bus_type')
+class_type = CachedType('struct class')
+
+
+def dev_name(dev):
+    dev_init_name = dev['init_name']
+    if dev_init_name:
+        return dev_init_name.string()
+    return dev['kobj']['name'].string()
+
+
+def kset_for_each_object(kset):
+    return list_for_each_entry(kset['list'],
+            kobject_type.get_type().pointer(), "entry")
+
+
+def for_each_bus():
+    for kobj in kset_for_each_object(gdb.parse_and_eval('bus_kset')):
+        subsys = container_of(kobj, kset_type.get_type().pointer(), 'kobj')
+        subsys_priv = container_of(subsys, subsys_private_type.get_type().pointer(), 'subsys')
+        yield subsys_priv['bus']
+
+
+def for_each_class():
+    for kobj in kset_for_each_object(gdb.parse_and_eval('class_kset')):
+        subsys = container_of(kobj, kset_type.get_type().pointer(), 'kobj')
+        subsys_priv = container_of(subsys, subsys_private_type.get_type().pointer(), 'subsys')
+        yield subsys_priv['class']
+
+
+def get_bus_by_name(name):
+    for item in for_each_bus():
+        if item['name'].string() == name:
+            return item
+    raise gdb.GdbError("Can't find bus type {!r}".format(name))
+
+
+def get_class_by_name(name):
+    for item in for_each_class():
+        if item['name'].string() == name:
+            return item
+    raise gdb.GdbError("Can't find device class {!r}".format(name))
+
+
+klist_type = CachedType('struct klist')
+klist_node_type = CachedType('struct klist_node')
+
+
+def klist_for_each(klist):
+    return list_for_each_entry(klist['k_list'],
+                klist_node_type.get_type().pointer(), 'n_node')
+
+
+def bus_for_each_device(bus):
+    for kn in klist_for_each(bus['p']['klist_devices']):
+        dp = container_of(kn, device_private_type.get_type().pointer(), 'knode_bus')
+        yield dp['device']
+
+
+def class_for_each_device(cls):
+    for kn in klist_for_each(cls['p']['klist_devices']):
+        dp = container_of(kn, device_private_type.get_type().pointer(), 'knode_class')
+        yield dp['device']
+
+
+def device_for_each_child(dev):
+    for kn in klist_for_each(dev['p']['klist_children']):
+        dp = container_of(kn, device_private_type.get_type().pointer(), 'knode_parent')
+        yield dp['device']
+
+
+def _show_device(dev, level=0, recursive=False):
+    gdb.write('{}dev {}:\t{}\n'.format('\t' * level, dev_name(dev), dev))
+    if recursive:
+        for child in device_for_each_child(dev):
+            _show_device(child, level + 1, recursive)
+
+
+class LxDeviceListBus(gdb.Command):
+    '''Print devices on a bus (or all buses if not specified)'''
+
+    def __init__(self):
+        super(LxDeviceListBus, self).__init__('lx-device-list-bus', gdb.COMMAND_DATA)
+
+    def invoke(self, arg, from_tty):
+        if not arg:
+            for bus in for_each_bus():
+                gdb.write('bus {}:\t{}\n'.format(bus['name'].string(), bus))
+                for dev in bus_for_each_device(bus):
+                    _show_device(dev, level=1)
+        else:
+            bus = get_bus_by_name(arg)
+            if not bus:
+                raise gdb.GdbError("Can't find bus {!r}".format(arg))
+            for dev in bus_for_each_device(bus):
+                _show_device(dev)
+
+
+class LxDeviceListClass(gdb.Command):
+    '''Print devices in a class (or all classes if not specified)'''
+
+    def __init__(self):
+        super(LxDeviceListClass, self).__init__('lx-device-list-class', gdb.COMMAND_DATA)
+
+    def invoke(self, arg, from_tty):
+        if not arg:
+            for cls in for_each_class():
+                gdb.write("class {}:\t{}\n".format(cls['name'].string(), cls))
+                for dev in class_for_each_device(cls):
+                    _show_device(dev, level=1)
+        else:
+            cls = get_class_by_name(arg)
+            for dev in class_for_each_device(cls):
+                _show_device(dev)
+
+
+class LxDeviceListTree(gdb.Command):
+    '''Print a device and its children recursively'''
+
+    def __init__(self):
+        super(LxDeviceListTree, self).__init__('lx-device-list-tree', gdb.COMMAND_DATA)
+
+    def invoke(self, arg, from_tty):
+        if not arg:
+            raise gdb.GdbError('Please provide pointer to struct device')
+        dev = gdb.parse_and_eval(arg)
+        if dev.type != device_type.get_type().pointer():
+            raise gdb.GdbError('Please provide pointer to struct device')
+        _show_device(dev, level=0, recursive=True)
+
+
+class LxDeviceFindByBusName(gdb.Function):
+    '''Find struct device by bus and name (both strings)'''
+
+    def __init__(self):
+        super(LxDeviceFindByBusName, self).__init__('lx_device_find_by_bus_name')
+
+    def invoke(self, bus, name):
+        name = name.string()
+        bus = get_bus_by_name(bus.string())
+        for dev in bus_for_each_device(bus):
+            if dev_name(dev) == name:
+                return dev
+
+
+class LxDeviceFindByClassName(gdb.Function):
+    '''Find struct device by class and name (both strings)'''
+
+    def __init__(self):
+        super(LxDeviceFindByClassName, self).__init__('lx_device_find_by_class_name')
+
+    def invoke(self, cls, name):
+        name = name.string()
+        cls = get_class_by_name(cls.string())
+        for dev in class_for_each_device(cls):
+            if dev_name(dev) == name:
+                return dev
+
+
+LxDeviceListBus()
+LxDeviceListClass()
+LxDeviceListTree()
+LxDeviceFindByBusName()
+LxDeviceFindByClassName()
diff --git a/marvell/linux/scripts/gdb/linux/dmesg.py b/marvell/linux/scripts/gdb/linux/dmesg.py
new file mode 100644
index 0000000..2fa7bb8
--- /dev/null
+++ b/marvell/linux/scripts/gdb/linux/dmesg.py
@@ -0,0 +1,81 @@
+#
+# gdb helper commands and functions for Linux kernel debugging
+#
+#  kernel log buffer dump
+#
+# Copyright (c) Siemens AG, 2011, 2012
+#
+# Authors:
+#  Jan Kiszka <jan.kiszka@siemens.com>
+#
+# This work is licensed under the terms of the GNU GPL version 2.
+#
+
+import gdb
+import sys
+
+from linux import utils
+
+printk_log_type = utils.CachedType("struct printk_log")
+
+
+class LxDmesg(gdb.Command):
+    """Print Linux kernel log buffer."""
+
+    def __init__(self):
+        super(LxDmesg, self).__init__("lx-dmesg", gdb.COMMAND_DATA)
+
+    def invoke(self, arg, from_tty):
+        log_buf_addr = int(str(gdb.parse_and_eval(
+            "(void *)'printk.c'::log_buf")).split()[0], 16)
+        log_first_idx = int(gdb.parse_and_eval("'printk.c'::log_first_idx"))
+        log_next_idx = int(gdb.parse_and_eval("'printk.c'::log_next_idx"))
+        log_buf_len = int(gdb.parse_and_eval("'printk.c'::log_buf_len"))
+
+        inf = gdb.inferiors()[0]
+        start = log_buf_addr + log_first_idx
+        if log_first_idx < log_next_idx:
+            log_buf_2nd_half = -1
+            length = log_next_idx - log_first_idx
+            log_buf = utils.read_memoryview(inf, start, length).tobytes()
+        else:
+            log_buf_2nd_half = log_buf_len - log_first_idx
+            a = utils.read_memoryview(inf, start, log_buf_2nd_half)
+            b = utils.read_memoryview(inf, log_buf_addr, log_next_idx)
+            log_buf = a.tobytes() + b.tobytes()
+
+        length_offset = printk_log_type.get_type()['len'].bitpos // 8
+        text_len_offset = printk_log_type.get_type()['text_len'].bitpos // 8
+        time_stamp_offset = printk_log_type.get_type()['ts_nsec'].bitpos // 8
+        text_offset = printk_log_type.get_type().sizeof
+
+        pos = 0
+        while pos < log_buf.__len__():
+            length = utils.read_u16(log_buf, pos + length_offset)
+            if length == 0:
+                if log_buf_2nd_half == -1:
+                    gdb.write("Corrupted log buffer!\n")
+                    break
+                pos = log_buf_2nd_half
+                continue
+
+            text_len = utils.read_u16(log_buf, pos + text_len_offset)
+            text_start = pos + text_offset
+            text = log_buf[text_start:text_start + text_len].decode(
+                encoding='utf8', errors='replace')
+            time_stamp = utils.read_u64(log_buf, pos + time_stamp_offset)
+
+            for line in text.splitlines():
+                msg = u"[{time:12.6f}] {line}\n".format(
+                    time=time_stamp / 1000000000.0,
+                    line=line)
+                # With python2 gdb.write will attempt to convert unicode to
+                # ascii and might fail so pass an utf8-encoded str instead.
+                if sys.hexversion < 0x03000000:
+                    msg = msg.encode(encoding='utf8', errors='replace')
+                gdb.write(msg)
+
+            pos += length
+
+
+LxDmesg()
diff --git a/marvell/linux/scripts/gdb/linux/genpd.py b/marvell/linux/scripts/gdb/linux/genpd.py
new file mode 100644
index 0000000..b53649c
--- /dev/null
+++ b/marvell/linux/scripts/gdb/linux/genpd.py
@@ -0,0 +1,85 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (c) NXP 2019
+
+import gdb
+import sys
+
+from linux.utils import CachedType, gdb_eval_or_none
+from linux.lists import list_for_each_entry
+
+generic_pm_domain_type = CachedType('struct generic_pm_domain')
+pm_domain_data_type = CachedType('struct pm_domain_data')
+device_link_type = CachedType('struct device_link')
+
+
+def kobject_get_path(kobj):
+    path = kobj['name'].string()
+    parent = kobj['parent']
+    if parent:
+        path = kobject_get_path(parent) + '/' + path
+    return path
+
+
+def rtpm_status_str(dev):
+    if dev['power']['runtime_error']:
+        return 'error'
+    if dev['power']['disable_depth']:
+        return 'unsupported'
+    _RPM_STATUS_LOOKUP = [
+        "active",
+        "resuming",
+        "suspended",
+        "suspending"
+    ]
+    return _RPM_STATUS_LOOKUP[dev['power']['runtime_status']]
+
+
+class LxGenPDSummary(gdb.Command):
+    '''Print genpd summary
+
+Output is similar to /sys/kernel/debug/pm_genpd/pm_genpd_summary'''
+
+    def __init__(self):
+        super(LxGenPDSummary, self).__init__('lx-genpd-summary', gdb.COMMAND_DATA)
+
+    def summary_one(self, genpd):
+        if genpd['status'] == 0:
+            status_string = 'on'
+        else:
+            status_string = 'off-{}'.format(genpd['state_idx'])
+
+        child_names = []
+        for link in list_for_each_entry(
+                genpd['parent_links'],
+                device_link_type.get_type().pointer(),
+                'parent_node'):
+            child_names.append(link['child']['name'])
+
+        gdb.write('%-30s  %-15s %s\n' % (
+                genpd['name'].string(),
+                status_string,
+                ', '.join(child_names)))
+
+        # Print devices in domain
+        for pm_data in list_for_each_entry(genpd['dev_list'],
+                        pm_domain_data_type.get_type().pointer(),
+                        'list_node'):
+            dev = pm_data['dev']
+            kobj_path = kobject_get_path(dev['kobj'])
+            gdb.write('    %-50s  %s\n' % (kobj_path, rtpm_status_str(dev)))
+
+    def invoke(self, arg, from_tty):
+        if gdb_eval_or_none("&gpd_list") is None:
+            raise gdb.GdbError("No power domain(s) registered")
+        gdb.write('domain                          status          children\n');
+        gdb.write('    /device                                             runtime status\n');
+        gdb.write('----------------------------------------------------------------------\n');
+        for genpd in list_for_each_entry(
+                gdb.parse_and_eval('&gpd_list'),
+                generic_pm_domain_type.get_type().pointer(),
+                'gpd_list_node'):
+            self.summary_one(genpd)
+
+
+LxGenPDSummary()
diff --git a/marvell/linux/scripts/gdb/linux/lists.py b/marvell/linux/scripts/gdb/linux/lists.py
new file mode 100644
index 0000000..c487ddf
--- /dev/null
+++ b/marvell/linux/scripts/gdb/linux/lists.py
@@ -0,0 +1,131 @@
+#
+# gdb helper commands and functions for Linux kernel debugging
+#
+#  list tools
+#
+# Copyright (c) Thiebaud Weksteen, 2015
+#
+# Authors:
+#  Thiebaud Weksteen <thiebaud@weksteen.fr>
+#
+# This work is licensed under the terms of the GNU GPL version 2.
+#
+
+import gdb
+
+from linux import utils
+
+list_head = utils.CachedType("struct list_head")
+hlist_head = utils.CachedType("struct hlist_head")
+hlist_node = utils.CachedType("struct hlist_node")
+
+
+def list_for_each(head):
+    if head.type == list_head.get_type().pointer():
+        head = head.dereference()
+    elif head.type != list_head.get_type():
+        raise TypeError("Must be struct list_head not {}"
+                           .format(head.type))
+
+    node = head['next'].dereference()
+    while node.address != head.address:
+        yield node.address
+        node = node['next'].dereference()
+
+
+def list_for_each_entry(head, gdbtype, member):
+    for node in list_for_each(head):
+        yield utils.container_of(node, gdbtype, member)
+
+
+def hlist_for_each(head):
+    if head.type == hlist_head.get_type().pointer():
+        head = head.dereference()
+    elif head.type != hlist_head.get_type():
+        raise TypeError("Must be struct hlist_head not {}"
+                           .format(head.type))
+
+    node = head['first'].dereference()
+    while node.address:
+        yield node.address
+        node = node['next'].dereference()
+
+
+def hlist_for_each_entry(head, gdbtype, member):
+    for node in hlist_for_each(head):
+        yield utils.container_of(node, gdbtype, member)
+
+
+def list_check(head):
+    nb = 0
+    if (head.type == list_head.get_type().pointer()):
+        head = head.dereference()
+    elif (head.type != list_head.get_type()):
+        raise gdb.GdbError('argument must be of type (struct list_head [*])')
+    c = head
+    try:
+        gdb.write("Starting with: {}\n".format(c))
+    except gdb.MemoryError:
+        gdb.write('head is not accessible\n')
+        return
+    while True:
+        p = c['prev'].dereference()
+        n = c['next'].dereference()
+        try:
+            if p['next'] != c.address:
+                gdb.write('prev.next != current: '
+                          'current@{current_addr}={current} '
+                          'prev@{p_addr}={p}\n'.format(
+                              current_addr=c.address,
+                              current=c,
+                              p_addr=p.address,
+                              p=p,
+                          ))
+                return
+        except gdb.MemoryError:
+            gdb.write('prev is not accessible: '
+                      'current@{current_addr}={current}\n'.format(
+                          current_addr=c.address,
+                          current=c
+                      ))
+            return
+        try:
+            if n['prev'] != c.address:
+                gdb.write('next.prev != current: '
+                          'current@{current_addr}={current} '
+                          'next@{n_addr}={n}\n'.format(
+                              current_addr=c.address,
+                              current=c,
+                              n_addr=n.address,
+                              n=n,
+                          ))
+                return
+        except gdb.MemoryError:
+            gdb.write('next is not accessible: '
+                      'current@{current_addr}={current}\n'.format(
+                          current_addr=c.address,
+                          current=c
+                      ))
+            return
+        c = n
+        nb += 1
+        if c == head:
+            gdb.write("list is consistent: {} node(s)\n".format(nb))
+            return
+
+
+class LxListChk(gdb.Command):
+    """Verify a list consistency"""
+
+    def __init__(self):
+        super(LxListChk, self).__init__("lx-list-check", gdb.COMMAND_DATA,
+                                        gdb.COMPLETE_EXPRESSION)
+
+    def invoke(self, arg, from_tty):
+        argv = gdb.string_to_argv(arg)
+        if len(argv) != 1:
+            raise gdb.GdbError("lx-list-check takes one argument")
+        list_check(gdb.parse_and_eval(argv[0]))
+
+
+LxListChk()
diff --git a/marvell/linux/scripts/gdb/linux/modules.py b/marvell/linux/scripts/gdb/linux/modules.py
new file mode 100644
index 0000000..441b232
--- /dev/null
+++ b/marvell/linux/scripts/gdb/linux/modules.py
@@ -0,0 +1,95 @@
+#
+# gdb helper commands and functions for Linux kernel debugging
+#
+#  module tools
+#
+# Copyright (c) Siemens AG, 2013
+#
+# Authors:
+#  Jan Kiszka <jan.kiszka@siemens.com>
+#
+# This work is licensed under the terms of the GNU GPL version 2.
+#
+
+import gdb
+
+from linux import cpus, utils, lists
+
+
+module_type = utils.CachedType("struct module")
+
+
+def module_list():
+    global module_type
+    modules = utils.gdb_eval_or_none("modules")
+    if modules is None:
+        return
+
+    module_ptr_type = module_type.get_type().pointer()
+
+    for module in lists.list_for_each_entry(modules, module_ptr_type, "list"):
+        yield module
+
+
+def find_module_by_name(name):
+    for module in module_list():
+        if module['name'].string() == name:
+            return module
+    return None
+
+
+class LxModule(gdb.Function):
+    """Find module by name and return the module variable.
+
+$lx_module("MODULE"): Given the name MODULE, iterate over all loaded modules
+of the target and return that module variable which MODULE matches."""
+
+    def __init__(self):
+        super(LxModule, self).__init__("lx_module")
+
+    def invoke(self, mod_name):
+        mod_name = mod_name.string()
+        module = find_module_by_name(mod_name)
+        if module:
+            return module.dereference()
+        else:
+            raise gdb.GdbError("Unable to find MODULE " + mod_name)
+
+
+LxModule()
+
+
+class LxLsmod(gdb.Command):
+    """List currently loaded modules."""
+
+    _module_use_type = utils.CachedType("struct module_use")
+
+    def __init__(self):
+        super(LxLsmod, self).__init__("lx-lsmod", gdb.COMMAND_DATA)
+
+    def invoke(self, arg, from_tty):
+        gdb.write(
+            "Address{0}    Module                  Size  Used by\n".format(
+                "        " if utils.get_long_type().sizeof == 8 else ""))
+
+        for module in module_list():
+            layout = module['core_layout']
+            gdb.write("{address} {name:<19} {size:>8}  {ref}".format(
+                address=str(layout['base']).split()[0],
+                name=module['name'].string(),
+                size=str(layout['size']),
+                ref=str(module['refcnt']['counter'] - 1)))
+
+            t = self._module_use_type.get_type().pointer()
+            first = True
+            sources = module['source_list']
+            for use in lists.list_for_each_entry(sources, t, "source_list"):
+                gdb.write("{separator}{name}".format(
+                    separator=" " if first else ",",
+                    name=use['source']['name'].string()))
+                first = False
+
+            gdb.write("\n")
+
+
+LxLsmod()
diff --git a/marvell/linux/scripts/gdb/linux/proc.py b/marvell/linux/scripts/gdb/linux/proc.py
new file mode 100644
index 0000000..6a56bba
--- /dev/null
+++ b/marvell/linux/scripts/gdb/linux/proc.py
@@ -0,0 +1,276 @@
+#
+# gdb helper commands and functions for Linux kernel debugging
+#
+#  Kernel proc information reader
+#
+# Copyright (c) 2016 Linaro Ltd
+#
+# Authors:
+#  Kieran Bingham <kieran.bingham@linaro.org>
+#
+# This work is licensed under the terms of the GNU GPL version 2.
+#
+
+import gdb
+from linux import constants
+from linux import utils
+from linux import tasks
+from linux import lists
+from struct import *
+
+
+class LxCmdLine(gdb.Command):
+    """ Report the Linux Commandline used in the current kernel.
+        Equivalent to cat /proc/cmdline on a running target"""
+
+    def __init__(self):
+        super(LxCmdLine, self).__init__("lx-cmdline", gdb.COMMAND_DATA)
+
+    def invoke(self, arg, from_tty):
+        gdb.write(gdb.parse_and_eval("saved_command_line").string() + "\n")
+
+
+LxCmdLine()
+
+
+class LxVersion(gdb.Command):
+    """ Report the Linux Version of the current kernel.
+        Equivalent to cat /proc/version on a running target"""
+
+    def __init__(self):
+        super(LxVersion, self).__init__("lx-version", gdb.COMMAND_DATA)
+
+    def invoke(self, arg, from_tty):
+        # linux_banner should contain a newline
+        gdb.write(gdb.parse_and_eval("(char *)linux_banner").string())
+
+
+LxVersion()
+
+
+# Resource Structure Printers
+#  /proc/iomem
+#  /proc/ioports
+
+def get_resources(resource, depth):
+    while resource:
+        yield resource, depth
+
+        child = resource['child']
+        if child:
+            for res, deep in get_resources(child, depth + 1):
+                yield res, deep
+
+        resource = resource['sibling']
+
+
+def show_lx_resources(resource_str):
+        resource = gdb.parse_and_eval(resource_str)
+        width = 4 if resource['end'] < 0x10000 else 8
+        # Iterate straight to the first child
+        for res, depth in get_resources(resource['child'], 0):
+            start = int(res['start'])
+            end = int(res['end'])
+            gdb.write(" " * depth * 2 +
+                      "{0:0{1}x}-".format(start, width) +
+                      "{0:0{1}x} : ".format(end, width) +
+                      res['name'].string() + "\n")
+
+
+class LxIOMem(gdb.Command):
+    """Identify the IO memory resource locations defined by the kernel
+
+Equivalent to cat /proc/iomem on a running target"""
+
+    def __init__(self):
+        super(LxIOMem, self).__init__("lx-iomem", gdb.COMMAND_DATA)
+
+    def invoke(self, arg, from_tty):
+        return show_lx_resources("iomem_resource")
+
+
+LxIOMem()
+
+
+class LxIOPorts(gdb.Command):
+    """Identify the IO port resource locations defined by the kernel
+
+Equivalent to cat /proc/ioports on a running target"""
+
+    def __init__(self):
+        super(LxIOPorts, self).__init__("lx-ioports", gdb.COMMAND_DATA)
+
+    def invoke(self, arg, from_tty):
+        return show_lx_resources("ioport_resource")
+
+
+LxIOPorts()
+
+
+# Mount namespace viewer
+#  /proc/mounts
+
+def info_opts(lst, opt):
+    opts = ""
+    for key, string in lst.items():
+        if opt & key:
+            opts += string
+    return opts
+
+
+FS_INFO = {constants.LX_SB_SYNCHRONOUS: ",sync",
+           constants.LX_SB_MANDLOCK: ",mand",
+           constants.LX_SB_DIRSYNC: ",dirsync",
+           constants.LX_SB_NOATIME: ",noatime",
+           constants.LX_SB_NODIRATIME: ",nodiratime"}
+
+MNT_INFO = {constants.LX_MNT_NOSUID: ",nosuid",
+            constants.LX_MNT_NODEV: ",nodev",
+            constants.LX_MNT_NOEXEC: ",noexec",
+            constants.LX_MNT_NOATIME: ",noatime",
+            constants.LX_MNT_NODIRATIME: ",nodiratime",
+            constants.LX_MNT_RELATIME: ",relatime"}
+
+mount_type = utils.CachedType("struct mount")
+mount_ptr_type = mount_type.get_type().pointer()
+
+
+class LxMounts(gdb.Command):
+    """Report the VFS mounts of the current process namespace.
+
+Equivalent to cat /proc/mounts on a running target
+An integer value can be supplied to display the mount
+values of that process namespace"""
+
+    def __init__(self):
+        super(LxMounts, self).__init__("lx-mounts", gdb.COMMAND_DATA)
+
+    # Equivalent to proc_namespace.c:show_vfsmnt
+    # However, that has the ability to call into s_op functions
+    # whereas we cannot and must make do with the information we can obtain.
+    def invoke(self, arg, from_tty):
+        argv = gdb.string_to_argv(arg)
+        if len(argv) >= 1:
+            try:
+                pid = int(argv[0])
+            except gdb.error:
+                raise gdb.GdbError("Provide a PID as integer value")
+        else:
+            pid = 1
+
+        task = tasks.get_task_by_pid(pid)
+        if not task:
+            raise gdb.GdbError("Couldn't find a process with PID {}"
+                               .format(pid))
+
+        namespace = task['nsproxy']['mnt_ns']
+        if not namespace:
+            raise gdb.GdbError("No namespace for current process")
+
+        for vfs in lists.list_for_each_entry(namespace['list'],
+                                             mount_ptr_type, "mnt_list"):
+            devname = vfs['mnt_devname'].string()
+            devname = devname if devname else "none"
+
+            pathname = ""
+            parent = vfs
+            while True:
+                mntpoint = parent['mnt_mountpoint']
+                pathname = utils.dentry_name(mntpoint) + pathname
+                if (parent == parent['mnt_parent']):
+                    break
+                parent = parent['mnt_parent']
+
+            if (pathname == ""):
+                pathname = "/"
+
+            superblock = vfs['mnt']['mnt_sb']
+            fstype = superblock['s_type']['name'].string()
+            s_flags = int(superblock['s_flags'])
+            m_flags = int(vfs['mnt']['mnt_flags'])
+            rd = "ro" if (s_flags & constants.LX_SB_RDONLY) else "rw"
+
+            gdb.write(
+                "{} {} {} {}{}{} 0 0\n"
+                .format(devname,
+                        pathname,
+                        fstype,
+                        rd,
+                        info_opts(FS_INFO, s_flags),
+                        info_opts(MNT_INFO, m_flags)))
+
+
+LxMounts()
+
+
+class LxFdtDump(gdb.Command):
+    """Output Flattened Device Tree header and dump FDT blob to the filename
+       specified as the command argument. Equivalent to
+       'cat /proc/fdt > fdtdump.dtb' on a running target"""
+
+    def __init__(self):
+        super(LxFdtDump, self).__init__("lx-fdtdump", gdb.COMMAND_DATA,
+                                        gdb.COMPLETE_FILENAME)
+
+    def fdthdr_to_cpu(self, fdt_header):
+
+        fdt_header_be = ">IIIIIII"
+        fdt_header_le = "<IIIIIII"
+
+        if utils.get_target_endianness() == 1:
+            output_fmt = fdt_header_le
+        else:
+            output_fmt = fdt_header_be
+
+        return unpack(output_fmt, pack(fdt_header_be,
+                                       fdt_header['magic'],
+                                       fdt_header['totalsize'],
+                                       fdt_header['off_dt_struct'],
+                                       fdt_header['off_dt_strings'],
+                                       fdt_header['off_mem_rsvmap'],
+                                       fdt_header['version'],
+                                       fdt_header['last_comp_version']))
+
+    def invoke(self, arg, from_tty):
+
+        if not constants.LX_CONFIG_OF:
+            raise gdb.GdbError("Kernel not compiled with CONFIG_OF\n")
+
+        if len(arg) == 0:
+            filename = "fdtdump.dtb"
+        else:
+            filename = arg
+
+        py_fdt_header_ptr = gdb.parse_and_eval(
+            "(const struct fdt_header *) initial_boot_params")
+        py_fdt_header = py_fdt_header_ptr.dereference()
+
+        fdt_header = self.fdthdr_to_cpu(py_fdt_header)
+
+        if fdt_header[0] != constants.LX_OF_DT_HEADER:
+            raise gdb.GdbError("No flattened device tree magic found\n")
+
+        gdb.write("fdt_magic:         0x{:02X}\n".format(fdt_header[0]))
+        gdb.write("fdt_totalsize:     0x{:02X}\n".format(fdt_header[1]))
+        gdb.write("off_dt_struct:     0x{:02X}\n".format(fdt_header[2]))
+        gdb.write("off_dt_strings:    0x{:02X}\n".format(fdt_header[3]))
+        gdb.write("off_mem_rsvmap:    0x{:02X}\n".format(fdt_header[4]))
+        gdb.write("version:           {}\n".format(fdt_header[5]))
+        gdb.write("last_comp_version: {}\n".format(fdt_header[6]))
+
+        inf = gdb.inferiors()[0]
+        fdt_buf = utils.read_memoryview(inf, py_fdt_header_ptr,
+                                        fdt_header[1]).tobytes()
+
+        try:
+            f = open(filename, 'wb')
+        except gdb.error:
+            raise gdb.GdbError("Could not open file to dump fdt")
+
+        f.write(fdt_buf)
+        f.close()
+
+        gdb.write("Dumped fdt blob to " + filename + "\n")
+
+
+LxFdtDump()
diff --git a/marvell/linux/scripts/gdb/linux/rbtree.py b/marvell/linux/scripts/gdb/linux/rbtree.py
new file mode 100644
index 0000000..c4b9916
--- /dev/null
+++ b/marvell/linux/scripts/gdb/linux/rbtree.py
@@ -0,0 +1,177 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright 2019 Google LLC.
+
+import gdb
+
+from linux import utils
+
+rb_root_type = utils.CachedType("struct rb_root")
+rb_node_type = utils.CachedType("struct rb_node")
+
+
+def rb_first(root):
+    if root.type == rb_root_type.get_type():
+        node = root.address.cast(rb_root_type.get_type().pointer())
+    elif root.type != rb_root_type.get_type().pointer():
+        raise gdb.GdbError("Must be struct rb_root not {}".format(root.type))
+
+    node = root['rb_node']
+    if node is 0:
+        return None
+
+    while node['rb_left']:
+        node = node['rb_left']
+
+    return node
+
+
+def rb_last(root):
+    if root.type == rb_root_type.get_type():
+        node = root.address.cast(rb_root_type.get_type().pointer())
+    elif root.type != rb_root_type.get_type().pointer():
+        raise gdb.GdbError("Must be struct rb_root not {}".format(root.type))
+
+    node = root['rb_node']
+    if node is 0:
+        return None
+
+    while node['rb_right']:
+        node = node['rb_right']
+
+    return node
+
+
+def rb_parent(node):
+    parent = gdb.Value(node['__rb_parent_color'] & ~3)
+    return parent.cast(rb_node_type.get_type().pointer())
+
+
+def rb_empty_node(node):
+    return node['__rb_parent_color'] == node.address
+
+
+def rb_next(node):
+    if node.type == rb_node_type.get_type():
+        node = node.address.cast(rb_node_type.get_type().pointer())
+    elif node.type != rb_node_type.get_type().pointer():
+        raise gdb.GdbError("Must be struct rb_node not {}".format(node.type))
+
+    if rb_empty_node(node):
+        return None
+
+    if node['rb_right']:
+        node = node['rb_right']
+        while node['rb_left']:
+            node = node['rb_left']
+        return node
+
+    parent = rb_parent(node)
+    while parent and node == parent['rb_right']:
+            node = parent
+            parent = rb_parent(node)
+
+    return parent
+
+
+def rb_prev(node):
+    if node.type == rb_node_type.get_type():
+        node = node.address.cast(rb_node_type.get_type().pointer())
+    elif node.type != rb_node_type.get_type().pointer():
+        raise gdb.GdbError("Must be struct rb_node not {}".format(node.type))
+
+    if rb_empty_node(node):
+        return None
+
+    if node['rb_left']:
+        node = node['rb_left']
+        while node['rb_right']:
+            node = node['rb_right']
+        return node.dereference()
+
+    parent = rb_parent(node)
+    while parent and node == parent['rb_left'].dereference():
+            node = parent
+            parent = rb_parent(node)
+
+    return parent
+
+
+class LxRbFirst(gdb.Function):
+    """Lookup and return a node from an RBTree
+
+$lx_rb_first(root): Return the node at the given index.
+If index is omitted, the root node is dereferenced and returned."""
+
+    def __init__(self):
+        super(LxRbFirst, self).__init__("lx_rb_first")
+
+    def invoke(self, root):
+        result = rb_first(root)
+        if result is None:
+            raise gdb.GdbError("No entry in tree")
+
+        return result
+
+
+LxRbFirst()
+
+
+class LxRbLast(gdb.Function):
+    """Lookup and return a node from an RBTree.
+
+$lx_rb_last(root): Return the node at the given index.
+If index is omitted, the root node is dereferenced and returned."""
+
+    def __init__(self):
+        super(LxRbLast, self).__init__("lx_rb_last")
+
+    def invoke(self, root):
+        result = rb_last(root)
+        if result is None:
+            raise gdb.GdbError("No entry in tree")
+
+        return result
+
+
+LxRbLast()
+
+
+class LxRbNext(gdb.Function):
+    """Lookup and return a node from an RBTree.
+
+$lx_rb_next(node): Return the node at the given index.
+If index is omitted, the root node is dereferenced and returned."""
+
+    def __init__(self):
+        super(LxRbNext, self).__init__("lx_rb_next")
+
+    def invoke(self, node):
+        result = rb_next(node)
+        if result is None:
+            raise gdb.GdbError("No entry in tree")
+
+        return result
+
+
+LxRbNext()
+
+
+class LxRbPrev(gdb.Function):
+    """Lookup and return a node from an RBTree.
+
+$lx_rb_prev(node): Return the node at the given index.
+If index is omitted, the root node is dereferenced and returned."""
+
+    def __init__(self):
+        super(LxRbPrev, self).__init__("lx_rb_prev")
+
+    def invoke(self, node):
+        result = rb_prev(node)
+        if result is None:
+            raise gdb.GdbError("No entry in tree")
+
+        return result
+
+
+LxRbPrev()
diff --git a/marvell/linux/scripts/gdb/linux/symbols.py b/marvell/linux/scripts/gdb/linux/symbols.py
new file mode 100644
index 0000000..1be9763
--- /dev/null
+++ b/marvell/linux/scripts/gdb/linux/symbols.py
@@ -0,0 +1,187 @@
+#
+# gdb helper commands and functions for Linux kernel debugging
+#
+#  load kernel and module symbols
+#
+# Copyright (c) Siemens AG, 2011-2013
+#
+# Authors:
+#  Jan Kiszka <jan.kiszka@siemens.com>
+#
+# This work is licensed under the terms of the GNU GPL version 2.
+#
+
+import gdb
+import os
+import re
+
+from linux import modules, utils
+
+
+if hasattr(gdb, 'Breakpoint'):
+    class LoadModuleBreakpoint(gdb.Breakpoint):
+        def __init__(self, spec, gdb_command):
+            super(LoadModuleBreakpoint, self).__init__(spec, internal=True)
+            self.silent = True
+            self.gdb_command = gdb_command
+
+        def stop(self):
+            module = gdb.parse_and_eval("mod")
+            module_name = module['name'].string()
+            cmd = self.gdb_command
+
+            # enforce update if object file is not found
+            cmd.module_files_updated = False
+
+            # Disable pagination while reporting symbol (re-)loading.
+            # The console input is blocked in this context so that we would
+            # get stuck waiting for the user to acknowledge paged output.
+            show_pagination = gdb.execute("show pagination", to_string=True)
+            pagination = show_pagination.endswith("on.\n")
+            gdb.execute("set pagination off")
+
+            if module_name in cmd.loaded_modules:
+                gdb.write("refreshing all symbols to reload module "
+                          "'{0}'\n".format(module_name))
+                cmd.load_all_symbols()
+            else:
+                cmd.load_module_symbols(module)
+
+            # restore pagination state
+            gdb.execute("set pagination %s" % ("on" if pagination else "off"))
+
+            return False
+
+
+class LxSymbols(gdb.Command):
+    """(Re-)load symbols of Linux kernel and currently loaded modules.
+
+The kernel (vmlinux) is taken from the current working directly. Modules (.ko)
+are scanned recursively, starting in the same directory. Optionally, the module
+search path can be extended by a space separated list of paths passed to the
+lx-symbols command."""
+
+    module_paths = []
+    module_files = []
+    module_files_updated = False
+    loaded_modules = []
+    breakpoint = None
+
+    def __init__(self):
+        super(LxSymbols, self).__init__("lx-symbols", gdb.COMMAND_FILES,
+                                        gdb.COMPLETE_FILENAME)
+
+    def _update_module_files(self):
+        self.module_files = []
+        for path in self.module_paths:
+            gdb.write("scanning for modules in {0}\n".format(path))
+            for root, dirs, files in os.walk(path):
+                for name in files:
+                    if name.endswith(".ko") or name.endswith(".ko.debug"):
+                        self.module_files.append(root + "/" + name)
+        self.module_files_updated = True
+
+    def _get_module_file(self, module_name):
+        module_pattern = ".*/{0}\.ko(?:.debug)?$".format(
+            module_name.replace("_", r"[_\-]"))
+        for name in self.module_files:
+            if re.match(module_pattern, name) and os.path.exists(name):
+                return name
+        return None
+
+    def _section_arguments(self, module):
+        try:
+            sect_attrs = module['sect_attrs'].dereference()
+        except gdb.error:
+            return ""
+        attrs = sect_attrs['attrs']
+        section_name_to_address = {
+            attrs[n]['battr']['attr']['name'].string(): attrs[n]['address']
+            for n in range(int(sect_attrs['nsections']))}
+        args = []
+        for section_name in [".data", ".data..read_mostly", ".rodata", ".bss",
+                             ".text", ".text.hot", ".text.unlikely"]:
+            address = section_name_to_address.get(section_name)
+            if address:
+                args.append(" -s {name} {addr}".format(
+                    name=section_name, addr=str(address)))
+        return "".join(args)
+
+    def load_module_symbols(self, module):
+        module_name = module['name'].string()
+        module_addr = str(module['core_layout']['base']).split()[0]
+
+        module_file = self._get_module_file(module_name)
+        if not module_file and not self.module_files_updated:
+            self._update_module_files()
+            module_file = self._get_module_file(module_name)
+
+        if module_file:
+            if utils.is_target_arch('s390'):
+                # Module text is preceded by PLT stubs on s390.
+                module_arch = module['arch']
+                plt_offset = int(module_arch['plt_offset'])
+                plt_size = int(module_arch['plt_size'])
+                module_addr = hex(int(module_addr, 0) + plt_offset + plt_size)
+            gdb.write("loading @{addr}: {filename}\n".format(
+                addr=module_addr, filename=module_file))
+            cmdline = "add-symbol-file {filename} {addr}{sections}".format(
+                filename=module_file,
+                addr=module_addr,
+                sections=self._section_arguments(module))
+            gdb.execute(cmdline, to_string=True)
+            if module_name not in self.loaded_modules:
+                self.loaded_modules.append(module_name)
+        else:
+            gdb.write("no module object found for '{0}'\n".format(module_name))
+
+    def load_all_symbols(self):
+        gdb.write("loading vmlinux\n")
+
+        # Dropping symbols will disable all breakpoints. So save their states
+        # and restore them afterward.
+        saved_states = []
+        if hasattr(gdb, 'breakpoints') and not gdb.breakpoints() is None:
+            for bp in gdb.breakpoints():
+                saved_states.append({'breakpoint': bp, 'enabled': bp.enabled})
+
+        # drop all current symbols and reload vmlinux
+        orig_vmlinux = 'vmlinux'
+        for obj in gdb.objfiles():
+            if obj.filename.endswith('vmlinux'):
+                orig_vmlinux = obj.filename
+        gdb.execute("symbol-file", to_string=True)
+        gdb.execute("symbol-file {0}".format(orig_vmlinux))
+
+        self.loaded_modules = []
+        module_list = modules.module_list()
+        if not module_list:
+            gdb.write("no modules found\n")
+        else:
+            [self.load_module_symbols(module) for module in module_list]
+
+        for saved_state in saved_states:
+            saved_state['breakpoint'].enabled = saved_state['enabled']
+
+    def invoke(self, arg, from_tty):
+        self.module_paths = [os.path.expanduser(p) for p in arg.split()]
+        self.module_paths.append(os.getcwd())
+
+        # enforce update
+        self.module_files = []
+        self.module_files_updated = False
+
+        self.load_all_symbols()
+
+        if hasattr(gdb, 'Breakpoint'):
+            if self.breakpoint is not None:
+                self.breakpoint.delete()
+                self.breakpoint = None
+            self.breakpoint = LoadModuleBreakpoint(
+                "kernel/module.c:do_init_module", self)
+        else:
+            gdb.write("Note: symbol update on module loading not supported "
+                      "with this gdb version\n")
+
+
+LxSymbols()
diff --git a/marvell/linux/scripts/gdb/linux/tasks.py b/marvell/linux/scripts/gdb/linux/tasks.py
new file mode 100644
index 0000000..0301dc1
--- /dev/null
+++ b/marvell/linux/scripts/gdb/linux/tasks.py
@@ -0,0 +1,139 @@
+#
+# gdb helper commands and functions for Linux kernel debugging
+#
+#  task & thread tools
+#
+# Copyright (c) Siemens AG, 2011-2013
+#
+# Authors:
+#  Jan Kiszka <jan.kiszka@siemens.com>
+#
+# This work is licensed under the terms of the GNU GPL version 2.
+#
+
+import gdb
+
+from linux import utils
+
+
+task_type = utils.CachedType("struct task_struct")
+
+
+def task_lists():
+    task_ptr_type = task_type.get_type().pointer()
+    init_task = gdb.parse_and_eval("init_task").address
+    t = g = init_task
+
+    while True:
+        while True:
+            yield t
+
+            t = utils.container_of(t['thread_group']['next'],
+                                   task_ptr_type, "thread_group")
+            if t == g:
+                break
+
+        t = g = utils.container_of(g['tasks']['next'],
+                                   task_ptr_type, "tasks")
+        if t == init_task:
+            return
+
+
+def get_task_by_pid(pid):
+    for task in task_lists():
+        if int(task['pid']) == pid:
+            return task
+    return None
+
+
+class LxTaskByPidFunc(gdb.Function):
+    """Find Linux task by PID and return the task_struct variable.
+
+$lx_task_by_pid(PID): Given PID, iterate over all tasks of the target and
+return that task_struct variable which PID matches."""
+
+    def __init__(self):
+        super(LxTaskByPidFunc, self).__init__("lx_task_by_pid")
+
+    def invoke(self, pid):
+        task = get_task_by_pid(pid)
+        if task:
+            return task.dereference()
+        else:
+            raise gdb.GdbError("No task of PID " + str(pid))
+
+
+LxTaskByPidFunc()
+
+
+class LxPs(gdb.Command):
+    """Dump Linux tasks."""
+
+    def __init__(self):
+        super(LxPs, self).__init__("lx-ps", gdb.COMMAND_DATA)
+
+    def invoke(self, arg, from_tty):
+        for task in task_lists():
+            gdb.write("{address} {pid} {comm}\n".format(
+                address=task,
+                pid=task["pid"],
+                comm=task["comm"].string()))
+
+
+LxPs()
+
+
+thread_info_type = utils.CachedType("struct thread_info")
+
+ia64_task_size = None
+
+
+def get_thread_info(task):
+    thread_info_ptr_type = thread_info_type.get_type().pointer()
+    if utils.is_target_arch("ia64"):
+        global ia64_task_size
+        if ia64_task_size is None:
+            ia64_task_size = gdb.parse_and_eval("sizeof(struct task_struct)")
+        thread_info_addr = task.address + ia64_task_size
+        thread_info = thread_info_addr.cast(thread_info_ptr_type)
+    else:
+        if task.type.fields()[0].type == thread_info_type.get_type():
+            return task['thread_info']
+        thread_info = task['stack'].cast(thread_info_ptr_type)
+    return thread_info.dereference()
+
+
+class LxThreadInfoFunc (gdb.Function):
+    """Calculate Linux thread_info from task variable.
+
+$lx_thread_info(TASK): Given TASK, return the corresponding thread_info
+variable."""
+
+    def __init__(self):
+        super(LxThreadInfoFunc, self).__init__("lx_thread_info")
+
+    def invoke(self, task):
+        return get_thread_info(task)
+
+
+LxThreadInfoFunc()
+
+
+class LxThreadInfoByPidFunc (gdb.Function):
+    """Calculate Linux thread_info from task variable found by pid
+
+$lx_thread_info_by_pid(PID): Given PID, return the corresponding thread_info
+variable."""
+
+    def __init__(self):
+        super(LxThreadInfoByPidFunc, self).__init__("lx_thread_info_by_pid")
+
+    def invoke(self, pid):
+        task = get_task_by_pid(pid)
+        if task:
+            return get_thread_info(task.dereference())
+        else:
+            raise gdb.GdbError("No task of PID " + str(pid))
+
+
+LxThreadInfoByPidFunc()
diff --git a/marvell/linux/scripts/gdb/linux/timerlist.py b/marvell/linux/scripts/gdb/linux/timerlist.py
new file mode 100644
index 0000000..51def84
--- /dev/null
+++ b/marvell/linux/scripts/gdb/linux/timerlist.py
@@ -0,0 +1,221 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright 2019 Google LLC.
+
+import binascii
+import gdb
+
+from linux import constants
+from linux import cpus
+from linux import rbtree
+from linux import utils
+
+timerqueue_node_type = utils.CachedType("struct timerqueue_node").get_type()
+hrtimer_type = utils.CachedType("struct hrtimer").get_type()
+
+
+def ktime_get():
+    """Returns the current time, but not very accurately
+
+    We can't read the hardware timer itself to add any nanoseconds
+    that need to be added since we last stored the time in the
+    timekeeper. But this is probably good enough for debug purposes."""
+    tk_core = gdb.parse_and_eval("&tk_core")
+
+    return tk_core['timekeeper']['tkr_mono']['base']
+
+
+def print_timer(rb_node, idx):
+    timerqueue = utils.container_of(rb_node, timerqueue_node_type.pointer(),
+                                    "node")
+    timer = utils.container_of(timerqueue, hrtimer_type.pointer(), "node")
+
+    function = str(timer['function']).split(" ")[1].strip("<>")
+    softexpires = timer['_softexpires']
+    expires = timer['node']['expires']
+    now = ktime_get()
+
+    text = " #{}: <{}>, {}, ".format(idx, timer, function)
+    text += "S:{:02x}\n".format(int(timer['state']))
+    text += " # expires at {}-{} nsecs [in {} to {} nsecs]\n".format(
+            softexpires, expires, softexpires - now, expires - now)
+    return text
+
+
+def print_active_timers(base):
+    curr = base['active']['next']['node']
+    curr = curr.address.cast(rbtree.rb_node_type.get_type().pointer())
+    idx = 0
+    while curr:
+        yield print_timer(curr, idx)
+        curr = rbtree.rb_next(curr)
+        idx += 1
+
+
+def print_base(base):
+    text = " .base:       {}\n".format(base.address)
+    text += " .index:      {}\n".format(base['index'])
+
+    text += " .resolution: {} nsecs\n".format(constants.LX_hrtimer_resolution)
+
+    text += " .get_time:   {}\n".format(base['get_time'])
+    if constants.LX_CONFIG_HIGH_RES_TIMERS:
+        text += "  .offset:     {} nsecs\n".format(base['offset'])
+    text += "active timers:\n"
+    text += "".join([x for x in print_active_timers(base)])
+    return text
+
+
+def print_cpu(hrtimer_bases, cpu, max_clock_bases):
+    cpu_base = cpus.per_cpu(hrtimer_bases, cpu)
+    jiffies = gdb.parse_and_eval("jiffies_64")
+    tick_sched_ptr = gdb.parse_and_eval("&tick_cpu_sched")
+    ts = cpus.per_cpu(tick_sched_ptr, cpu)
+
+    text = "cpu: {}\n".format(cpu)
+    for i in range(max_clock_bases):
+        text += " clock {}:\n".format(i)
+        text += print_base(cpu_base['clock_base'][i])
+
+        if constants.LX_CONFIG_HIGH_RES_TIMERS:
+            fmts = [("  .{}   : {} nsecs", 'expires_next'),
+                    ("  .{}    : {}", 'hres_active'),
+                    ("  .{}      : {}", 'nr_events'),
+                    ("  .{}     : {}", 'nr_retries'),
+                    ("  .{}       : {}", 'nr_hangs'),
+                    ("  .{}  : {}", 'max_hang_time')]
+            text += "\n".join([s.format(f, cpu_base[f]) for s, f in fmts])
+            text += "\n"
+
+        if constants.LX_CONFIG_TICK_ONESHOT:
+            fmts = [("  .{}      : {}", 'nohz_mode'),
+                    ("  .{}      : {} nsecs", 'last_tick'),
+                    ("  .{}   : {}", 'tick_stopped'),
+                    ("  .{}   : {}", 'idle_jiffies'),
+                    ("  .{}     : {}", 'idle_calls'),
+                    ("  .{}    : {}", 'idle_sleeps'),
+                    ("  .{} : {} nsecs", 'idle_entrytime'),
+                    ("  .{}  : {} nsecs", 'idle_waketime'),
+                    ("  .{}  : {} nsecs", 'idle_exittime'),
+                    ("  .{} : {} nsecs", 'idle_sleeptime'),
+                    ("  .{}: {} nsecs", 'iowait_sleeptime'),
+                    ("  .{}   : {}", 'last_jiffies'),
+                    ("  .{}     : {}", 'next_timer'),
+                    ("  .{}   : {} nsecs", 'idle_expires')]
+            text += "\n".join([s.format(f, ts[f]) for s, f in fmts])
+            text += "\njiffies: {}\n".format(jiffies)
+
+        text += "\n"
+
+    return text
+
+
+def print_tickdevice(td, cpu):
+    dev = td['evtdev']
+    text = "Tick Device: mode:     {}\n".format(td['mode'])
+    if cpu < 0:
+            text += "Broadcast device\n"
+    else:
+            text += "Per CPU device: {}\n".format(cpu)
+
+    text += "Clock Event Device: "
+    if dev == 0:
+            text += "<NULL>\n"
+            return text
+
+    text += "{}\n".format(dev['name'])
+    text += " max_delta_ns:   {}\n".format(dev['max_delta_ns'])
+    text += " min_delta_ns:   {}\n".format(dev['min_delta_ns'])
+    text += " mult:           {}\n".format(dev['mult'])
+    text += " shift:          {}\n".format(dev['shift'])
+    text += " mode:           {}\n".format(dev['state_use_accessors'])
+    text += " next_event:     {} nsecs\n".format(dev['next_event'])
+
+    text += " set_next_event: {}\n".format(dev['set_next_event'])
+
+    members = [('set_state_shutdown', " shutdown: {}\n"),
+               ('set_state_periodic', " periodic: {}\n"),
+               ('set_state_oneshot', " oneshot:  {}\n"),
+               ('set_state_oneshot_stopped', " oneshot stopped: {}\n"),
+               ('tick_resume', " resume:   {}\n")]
+    for member, fmt in members:
+        if dev[member]:
+            text += fmt.format(dev[member])
+
+    text += " event_handler:  {}\n".format(dev['event_handler'])
+    text += " retries:        {}\n".format(dev['retries'])
+
+    return text
+
+
+def pr_cpumask(mask):
+    nr_cpu_ids = 1
+    if constants.LX_NR_CPUS > 1:
+        nr_cpu_ids = gdb.parse_and_eval("nr_cpu_ids")
+
+    inf = gdb.inferiors()[0]
+    bits = mask['bits']
+    num_bytes = (nr_cpu_ids + 7) / 8
+    buf = utils.read_memoryview(inf, bits, num_bytes).tobytes()
+    buf = binascii.b2a_hex(buf)
+    if type(buf) is not str:
+        buf=buf.decode()
+
+    chunks = []
+    i = num_bytes
+    while i > 0:
+        i -= 1
+        start = i * 2
+        end = start + 2
+        chunks.append(buf[start:end])
+        if i != 0 and i % 4 == 0:
+            chunks.append(',')
+
+    extra = nr_cpu_ids % 8
+    if 0 < extra <= 4:
+        chunks[0] = chunks[0][0]  # Cut off the first 0
+
+    return "".join(chunks)
+
+
+class LxTimerList(gdb.Command):
+    """Print /proc/timer_list"""
+
+    def __init__(self):
+        super(LxTimerList, self).__init__("lx-timerlist", gdb.COMMAND_DATA)
+
+    def invoke(self, arg, from_tty):
+        hrtimer_bases = gdb.parse_and_eval("&hrtimer_bases")
+        max_clock_bases = gdb.parse_and_eval("HRTIMER_MAX_CLOCK_BASES")
+
+        text = "Timer List Version: gdb scripts\n"
+        text += "HRTIMER_MAX_CLOCK_BASES: {}\n".format(max_clock_bases)
+        text += "now at {} nsecs\n".format(ktime_get())
+
+        for cpu in cpus.each_online_cpu():
+            text += print_cpu(hrtimer_bases, cpu, max_clock_bases)
+
+        if constants.LX_CONFIG_GENERIC_CLOCKEVENTS:
+            if constants.LX_CONFIG_GENERIC_CLOCKEVENTS_BROADCAST:
+                bc_dev = gdb.parse_and_eval("&tick_broadcast_device")
+                text += print_tickdevice(bc_dev, -1)
+                text += "\n"
+                mask = gdb.parse_and_eval("tick_broadcast_mask")
+                mask = pr_cpumask(mask)
+                text += "tick_broadcast_mask: {}\n".format(mask)
+                if constants.LX_CONFIG_TICK_ONESHOT:
+                    mask = gdb.parse_and_eval("tick_broadcast_oneshot_mask")
+                    mask = pr_cpumask(mask)
+                    text += "tick_broadcast_oneshot_mask: {}\n".format(mask)
+                text += "\n"
+
+            tick_cpu_devices = gdb.parse_and_eval("&tick_cpu_device")
+            for cpu in cpus.each_online_cpu():
+                tick_dev = cpus.per_cpu(tick_cpu_devices, cpu)
+                text += print_tickdevice(tick_dev, cpu)
+                text += "\n"
+
+        gdb.write(text)
+
+
+LxTimerList()
diff --git a/marvell/linux/scripts/gdb/linux/utils.py b/marvell/linux/scripts/gdb/linux/utils.py
new file mode 100644
index 0000000..8c33be7
--- /dev/null
+++ b/marvell/linux/scripts/gdb/linux/utils.py
@@ -0,0 +1,189 @@
+#
+# gdb helper commands and functions for Linux kernel debugging
+#
+#  common utilities
+#
+# Copyright (c) Siemens AG, 2011-2013
+#
+# Authors:
+#  Jan Kiszka <jan.kiszka@siemens.com>
+#
+# This work is licensed under the terms of the GNU GPL version 2.
+#
+
+import gdb
+
+
+class CachedType:
+    def __init__(self, name):
+        self._type = None
+        self._name = name
+
+    def _new_objfile_handler(self, event):
+        self._type = None
+        gdb.events.new_objfile.disconnect(self._new_objfile_handler)
+
+    def get_type(self):
+        if self._type is None:
+            self._type = gdb.lookup_type(self._name)
+            if self._type is None:
+                raise gdb.GdbError(
+                    "cannot resolve type '{0}'".format(self._name))
+            if hasattr(gdb, 'events') and hasattr(gdb.events, 'new_objfile'):
+                gdb.events.new_objfile.connect(self._new_objfile_handler)
+        return self._type
+
+
+long_type = CachedType("long")
+
+
+def get_long_type():
+    global long_type
+    return long_type.get_type()
+
+
+def offset_of(typeobj, field):
+    element = gdb.Value(0).cast(typeobj)
+    return int(str(element[field].address).split()[0], 16)
+
+
+def container_of(ptr, typeobj, member):
+    return (ptr.cast(get_long_type()) -
+            offset_of(typeobj, member)).cast(typeobj)
+
+
+class ContainerOf(gdb.Function):
+    """Return pointer to containing data structure.
+
+$container_of(PTR, "TYPE", "ELEMENT"): Given PTR, return a pointer to the
+data structure of the type TYPE in which PTR is the address of ELEMENT.
+Note that TYPE and ELEMENT have to be quoted as strings."""
+
+    def __init__(self):
+        super(ContainerOf, self).__init__("container_of")
+
+    def invoke(self, ptr, typename, elementname):
+        return container_of(ptr, gdb.lookup_type(typename.string()).pointer(),
+                            elementname.string())
+
+
+ContainerOf()
+
+
+BIG_ENDIAN = 0
+LITTLE_ENDIAN = 1
+target_endianness = None
+
+
+def get_target_endianness():
+    global target_endianness
+    if target_endianness is None:
+        endian = gdb.execute("show endian", to_string=True)
+        if "little endian" in endian:
+            target_endianness = LITTLE_ENDIAN
+        elif "big endian" in endian:
+            target_endianness = BIG_ENDIAN
+        else:
+            raise gdb.GdbError("unknown endianness '{0}'".format(str(endian)))
+    return target_endianness
+
+
+def read_memoryview(inf, start, length):
+    m = inf.read_memory(start, length)
+    if type(m) is memoryview:
+        return m
+    return memoryview(m)
+
+
+def read_u16(buffer, offset):
+    buffer_val = buffer[offset:offset + 2]
+    value = [0, 0]
+
+    if type(buffer_val[0]) is str:
+        value[0] = ord(buffer_val[0])
+        value[1] = ord(buffer_val[1])
+    else:
+        value[0] = buffer_val[0]
+        value[1] = buffer_val[1]
+
+    if get_target_endianness() == LITTLE_ENDIAN:
+        return value[0] + (value[1] << 8)
+    else:
+        return value[1] + (value[0] << 8)
+
+
+def read_u32(buffer, offset):
+    if get_target_endianness() == LITTLE_ENDIAN:
+        return read_u16(buffer, offset) + (read_u16(buffer, offset + 2) << 16)
+    else:
+        return read_u16(buffer, offset + 2) + (read_u16(buffer, offset) << 16)
+
+
+def read_u64(buffer, offset):
+    if get_target_endianness() == LITTLE_ENDIAN:
+        return read_u32(buffer, offset) + (read_u32(buffer, offset + 4) << 32)
+    else:
+        return read_u32(buffer, offset + 4) + (read_u32(buffer, offset) << 32)
+
+
+target_arch = None
+
+
+def is_target_arch(arch):
+    if hasattr(gdb.Frame, 'architecture'):
+        return arch in gdb.newest_frame().architecture().name()
+    else:
+        global target_arch
+        if target_arch is None:
+            target_arch = gdb.execute("show architecture", to_string=True)
+        return arch in target_arch
+
+
+GDBSERVER_QEMU = 0
+GDBSERVER_KGDB = 1
+gdbserver_type = None
+
+
+def get_gdbserver_type():
+    def exit_handler(event):
+        global gdbserver_type
+        gdbserver_type = None
+        gdb.events.exited.disconnect(exit_handler)
+
+    def probe_qemu():
+        try:
+            return gdb.execute("monitor info version", to_string=True) != ""
+        except gdb.error:
+            return False
+
+    def probe_kgdb():
+        try:
+            thread_info = gdb.execute("info thread 2", to_string=True)
+            return "shadowCPU0" in thread_info
+        except gdb.error:
+            return False
+
+    global gdbserver_type
+    if gdbserver_type is None:
+        if probe_qemu():
+            gdbserver_type = GDBSERVER_QEMU
+        elif probe_kgdb():
+            gdbserver_type = GDBSERVER_KGDB
+        if gdbserver_type is not None and hasattr(gdb, 'events'):
+            gdb.events.exited.connect(exit_handler)
+    return gdbserver_type
+
+
+def gdb_eval_or_none(expresssion):
+    try:
+        return gdb.parse_and_eval(expresssion)
+    except gdb.error:
+        return None
+
+
+def dentry_name(d):
+    parent = d['d_parent']
+    if parent == d or parent == 0:
+        return ""
+    p = dentry_name(d['d_parent']) + "/"
+    return p + d['d_iname'].string()
diff --git a/marvell/linux/scripts/gdb/vmlinux-gdb.py b/marvell/linux/scripts/gdb/vmlinux-gdb.py
new file mode 100644
index 0000000..4136dc2
--- /dev/null
+++ b/marvell/linux/scripts/gdb/vmlinux-gdb.py
@@ -0,0 +1,39 @@
+#
+# gdb helper commands and functions for Linux kernel debugging
+#
+#  loader module
+#
+# Copyright (c) Siemens AG, 2012, 2013
+#
+# Authors:
+#  Jan Kiszka <jan.kiszka@siemens.com>
+#
+# This work is licensed under the terms of the GNU GPL version 2.
+#
+
+import os
+
+sys.path.insert(0, os.path.dirname(__file__) + "/scripts/gdb")
+
+try:
+    gdb.parse_and_eval("0")
+    gdb.execute("", to_string=True)
+except:
+    gdb.write("NOTE: gdb 7.2 or later required for Linux helper scripts to "
+              "work.\n")
+else:
+    import linux.utils
+    import linux.symbols
+    import linux.modules
+    import linux.dmesg
+    import linux.tasks
+    import linux.config
+    import linux.cpus
+    import linux.lists
+    import linux.rbtree
+    import linux.proc
+    import linux.constants
+    import linux.timerlist
+    import linux.clk
+    import linux.genpd
+    import linux.device