# SPDX-License-Identifier: GPL-2.0
#
# Copyright (c) 2023 MediaTek Inc.
#
# Authors:
#  Kuan-Ying Lee <Kuan-Ying.Lee@mediatek.com>
#

import gdb
from linux import utils, stackdepot, constants, mm

if constants.LX_CONFIG_PAGE_OWNER:
    page_ext_t = utils.CachedType('struct page_ext')
    page_owner_t = utils.CachedType('struct page_owner')

    PAGE_OWNER_STACK_DEPTH = 16
    PAGE_EXT_OWNER = constants.LX_PAGE_EXT_OWNER
    PAGE_EXT_INVALID = 0x1
    PAGE_EXT_OWNER_ALLOCATED = constants.LX_PAGE_EXT_OWNER_ALLOCATED

def help():
    t = """Usage: lx-dump-page-owner [Option]
    Option:
        --pfn [Decimal pfn]
    Example:
        lx-dump-page-owner --pfn 655360\n"""
    gdb.write("Unrecognized command\n")
    raise gdb.GdbError(t)

class DumpPageOwner(gdb.Command):
    """Dump page owner"""

    min_pfn = None
    max_pfn = None
    p_ops = None
    migrate_reason_names = None

    def __init__(self):
        super(DumpPageOwner, self).__init__("lx-dump-page-owner", gdb.COMMAND_SUPPORT)

    def invoke(self, args, from_tty):
        if not constants.LX_CONFIG_PAGE_OWNER:
            raise gdb.GdbError('CONFIG_PAGE_OWNER does not enable')

        page_owner_inited = gdb.parse_and_eval('page_owner_inited')
        if page_owner_inited['key']['enabled']['counter'] != 0x1:
            raise gdb.GdbError('page_owner_inited is not enabled')

        self.p_ops = mm.page_ops().ops
        self.get_page_owner_info()
        argv = gdb.string_to_argv(args)
        if len(argv) == 0:
              self.read_page_owner()
        elif len(argv) == 2:
            if argv[0] == "--pfn":
                pfn = int(argv[1])
                self.read_page_owner_by_addr(self.p_ops.pfn_to_page(pfn))
            else:
                help()
        else:
            help()

    def get_page_owner_info(self):
        self.min_pfn = int(gdb.parse_and_eval("min_low_pfn"))
        self.max_pfn = int(gdb.parse_and_eval("max_pfn"))
        self.page_ext_size = int(gdb.parse_and_eval("page_ext_size"))
        self.migrate_reason_names = gdb.parse_and_eval('migrate_reason_names')

    def page_ext_invalid(self, page_ext):
        if page_ext == gdb.Value(0):
            return True
        if page_ext.cast(utils.get_ulong_type()) & PAGE_EXT_INVALID == PAGE_EXT_INVALID:
            return True
        return False

    def get_entry(self, base, index):
        return (base.cast(utils.get_ulong_type()) + self.page_ext_size * index).cast(page_ext_t.get_type().pointer())

    def lookup_page_ext(self, page):
        pfn = self.p_ops.page_to_pfn(page)
        section = self.p_ops.pfn_to_section(pfn)
        page_ext = section["page_ext"]
        if self.page_ext_invalid(page_ext):
            return gdb.Value(0)
        return self.get_entry(page_ext, pfn)

    def page_ext_get(self, page):
        page_ext = self.lookup_page_ext(page)
        if page_ext != gdb.Value(0):
            return page_ext
        else:
            return gdb.Value(0)

    def get_page_owner(self, page_ext):
        addr = page_ext.cast(utils.get_ulong_type()) + gdb.parse_and_eval("page_owner_ops")["offset"].cast(utils.get_ulong_type())
        return addr.cast(page_owner_t.get_type().pointer())

    def read_page_owner_by_addr(self, struct_page_addr):
        page = gdb.Value(struct_page_addr).cast(utils.get_page_type().pointer())
        pfn = self.p_ops.page_to_pfn(page)

        if pfn < self.min_pfn or pfn > self.max_pfn or (not self.p_ops.pfn_valid(pfn)):
            gdb.write("pfn is invalid\n")
            return

        page = self.p_ops.pfn_to_page(pfn)
        page_ext = self.page_ext_get(page)

        if page_ext == gdb.Value(0):
            gdb.write("page_ext is null\n")
            return

        if not (page_ext['flags'] & (1 << PAGE_EXT_OWNER)):
            gdb.write("page_owner flag is invalid\n")
            raise gdb.GdbError('page_owner info is not present (never set?)\n')

        if mm.test_bit(PAGE_EXT_OWNER_ALLOCATED, page_ext['flags'].address):
            gdb.write('page_owner tracks the page as allocated\n')
        else:
            gdb.write('page_owner tracks the page as freed\n')

        if not (page_ext['flags'] & (1 << PAGE_EXT_OWNER_ALLOCATED)):
            gdb.write("page_owner is not allocated\n")

        page_owner = self.get_page_owner(page_ext)
        gdb.write("Page last allocated via order %d, gfp_mask: 0x%x, pid: %d, tgid: %d (%s), ts %u ns, free_ts %u ns\n" %\
                (page_owner["order"], page_owner["gfp_mask"],\
                page_owner["pid"], page_owner["tgid"], page_owner["comm"].string(),\
                page_owner["ts_nsec"], page_owner["free_ts_nsec"]))
        gdb.write("PFN: %d, Flags: 0x%x\n" % (pfn, page['flags']))
        if page_owner["handle"] == 0:
            gdb.write('page_owner allocation stack trace missing\n')
        else:
            stackdepot.stack_depot_print(page_owner["handle"])

        if page_owner["free_handle"] == 0:
            gdb.write('page_owner free stack trace missing\n')
        else:
            gdb.write('page last free stack trace:\n')
            stackdepot.stack_depot_print(page_owner["free_handle"])
        if page_owner['last_migrate_reason'] != -1:
            gdb.write('page has been migrated, last migrate reason: %s\n' % self.migrate_reason_names[page_owner['last_migrate_reason']])

    def read_page_owner(self):
        pfn = self.min_pfn

        # Find a valid PFN or the start of a MAX_ORDER_NR_PAGES area
        while ((not self.p_ops.pfn_valid(pfn)) and (pfn & (self.p_ops.MAX_ORDER_NR_PAGES - 1))) != 0:
            pfn += 1

        while pfn < self.max_pfn:
            #
            # If the new page is in a new MAX_ORDER_NR_PAGES area,
            # validate the area as existing, skip it if not
            #
            if ((pfn & (self.p_ops.MAX_ORDER_NR_PAGES - 1)) == 0) and (not self.p_ops.pfn_valid(pfn)):
                pfn += (self.p_ops.MAX_ORDER_NR_PAGES - 1)
                continue;

            page = self.p_ops.pfn_to_page(pfn)
            page_ext = self.page_ext_get(page)
            if page_ext == gdb.Value(0):
                pfn += 1
                continue

            if not (page_ext['flags'] & (1 << PAGE_EXT_OWNER)):
                pfn += 1
                continue
            if not (page_ext['flags'] & (1 << PAGE_EXT_OWNER_ALLOCATED)):
                pfn += 1
                continue

            page_owner = self.get_page_owner(page_ext)
            gdb.write("Page allocated via order %d, gfp_mask: 0x%x, pid: %d, tgid: %d (%s), ts %u ns, free_ts %u ns\n" %\
                    (page_owner["order"], page_owner["gfp_mask"],\
                    page_owner["pid"], page_owner["tgid"], page_owner["comm"].string(),\
                    page_owner["ts_nsec"], page_owner["free_ts_nsec"]))
            gdb.write("PFN: %d, Flags: 0x%x\n" % (pfn, page['flags']))
            stackdepot.stack_depot_print(page_owner["handle"])
            pfn += (1 << page_owner["order"])

DumpPageOwner()
