From 9fdb12c88e9ba75e2d831fb397dd27f03a534968 Mon Sep 17 00:00:00 2001 From: Juri Lelli Date: Fri, 27 Jun 2025 13:51:17 +0200 Subject: [PATCH] tools/sched: Add root_domains_dump.py which dumps root domains info Root domains information is somewhat hard to access at runtime. Even with sched_debug and sched_verbose, such information is only printed on kernel console when domains are modified. Add a simple drgn script to more easily retrieve root domains information at runtime. Since tools/sched is a new directory, add it to MAINTAINERS as well. Signed-off-by: Juri Lelli Signed-off-by: Peter Zijlstra (Intel) Tested-by: Marcel Ziswiler # nuc & rock5b Link: https://lore.kernel.org/r/20250627115118.438797-5-juri.lelli@redhat.com --- MAINTAINERS | 1 + tools/sched/root_domains_dump.py | 68 ++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 tools/sched/root_domains_dump.py diff --git a/MAINTAINERS b/MAINTAINERS index a92290fffa163..b986a49383c9c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22165,6 +22165,7 @@ F: include/linux/wait.h F: include/uapi/linux/sched.h F: kernel/fork.c F: kernel/sched/ +F: tools/sched/ SCHEDULER - SCHED_EXT R: Tejun Heo diff --git a/tools/sched/root_domains_dump.py b/tools/sched/root_domains_dump.py new file mode 100644 index 0000000000000..56dc91f017b20 --- /dev/null +++ b/tools/sched/root_domains_dump.py @@ -0,0 +1,68 @@ +#!/usr/bin/env drgn +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2025 Juri Lelli +# Copyright (C) 2025 Red Hat, Inc. + +desc = """ +This is a drgn script to show the current root domains configuration. For more +info on drgn, visit https://github.com/osandov/drgn. + +Root domains are only printed once, as multiple CPUs might be attached to the +same root domain. +""" + +import os +import argparse + +import drgn +from drgn import FaultError +from drgn.helpers.common import * +from drgn.helpers.linux import * + +def print_root_domains_info(): + + # To store unique root domains found + seen_root_domains = set() + + print("Retrieving (unique) Root Domain Information:") + + runqueues = prog['runqueues'] + def_root_domain = prog['def_root_domain'] + + for cpu_id in for_each_possible_cpu(prog): + try: + rq = per_cpu(runqueues, cpu_id) + + root_domain = rq.rd + + # Check if we've already processed this root domain to avoid duplicates + # Use the memory address of the root_domain as a unique identifier + root_domain_cast = int(root_domain) + if root_domain_cast in seen_root_domains: + continue + seen_root_domains.add(root_domain_cast) + + if root_domain_cast == int(def_root_domain.address_): + print(f"\n--- Root Domain @ def_root_domain ---") + else: + print(f"\n--- Root Domain @ 0x{root_domain_cast:x} ---") + + print(f" From CPU: {cpu_id}") # This CPU belongs to this root domain + + # Access and print relevant fields from struct root_domain + print(f" Span : {cpumask_to_cpulist(root_domain.span[0])}") + print(f" Online : {cpumask_to_cpulist(root_domain.span[0])}") + + except drgn.FaultError as fe: + print(f" (CPU {cpu_id}: Fault accessing kernel memory: {fe})") + except AttributeError as ae: + print(f" (CPU {cpu_id}: Missing attribute for root_domain (kernel struct change?): {ae})") + except Exception as e: + print(f" (CPU {cpu_id}: An unexpected error occurred: {e})") + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description=desc, + formatter_class=argparse.RawTextHelpFormatter) + args = parser.parse_args() + + print_root_domains_info() -- 2.47.2