Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <juri.lelli@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Tested-by: Marcel Ziswiler <marcel.ziswiler@codethink.co.uk> # nuc & rock5b
Link: https://lore.kernel.org/r/20250627115118.438797-5-juri.lelli@redhat.com

authored by

Juri Lelli and committed by
Peter Zijlstra
9fdb12c8 440989c1

+69
+1
MAINTAINERS
··· 22165 22165 F: include/uapi/linux/sched.h 22166 22166 F: kernel/fork.c 22167 22167 F: kernel/sched/ 22168 + F: tools/sched/ 22168 22169 22169 22170 SCHEDULER - SCHED_EXT 22170 22171 R: Tejun Heo <tj@kernel.org>
+68
tools/sched/root_domains_dump.py
··· 1 + #!/usr/bin/env drgn 2 + # SPDX-License-Identifier: GPL-2.0 3 + # Copyright (C) 2025 Juri Lelli <juri.lelli@redhat.com> 4 + # Copyright (C) 2025 Red Hat, Inc. 5 + 6 + desc = """ 7 + This is a drgn script to show the current root domains configuration. For more 8 + info on drgn, visit https://github.com/osandov/drgn. 9 + 10 + Root domains are only printed once, as multiple CPUs might be attached to the 11 + same root domain. 12 + """ 13 + 14 + import os 15 + import argparse 16 + 17 + import drgn 18 + from drgn import FaultError 19 + from drgn.helpers.common import * 20 + from drgn.helpers.linux import * 21 + 22 + def print_root_domains_info(): 23 + 24 + # To store unique root domains found 25 + seen_root_domains = set() 26 + 27 + print("Retrieving (unique) Root Domain Information:") 28 + 29 + runqueues = prog['runqueues'] 30 + def_root_domain = prog['def_root_domain'] 31 + 32 + for cpu_id in for_each_possible_cpu(prog): 33 + try: 34 + rq = per_cpu(runqueues, cpu_id) 35 + 36 + root_domain = rq.rd 37 + 38 + # Check if we've already processed this root domain to avoid duplicates 39 + # Use the memory address of the root_domain as a unique identifier 40 + root_domain_cast = int(root_domain) 41 + if root_domain_cast in seen_root_domains: 42 + continue 43 + seen_root_domains.add(root_domain_cast) 44 + 45 + if root_domain_cast == int(def_root_domain.address_): 46 + print(f"\n--- Root Domain @ def_root_domain ---") 47 + else: 48 + print(f"\n--- Root Domain @ 0x{root_domain_cast:x} ---") 49 + 50 + print(f" From CPU: {cpu_id}") # This CPU belongs to this root domain 51 + 52 + # Access and print relevant fields from struct root_domain 53 + print(f" Span : {cpumask_to_cpulist(root_domain.span[0])}") 54 + print(f" Online : {cpumask_to_cpulist(root_domain.span[0])}") 55 + 56 + except drgn.FaultError as fe: 57 + print(f" (CPU {cpu_id}: Fault accessing kernel memory: {fe})") 58 + except AttributeError as ae: 59 + print(f" (CPU {cpu_id}: Missing attribute for root_domain (kernel struct change?): {ae})") 60 + except Exception as e: 61 + print(f" (CPU {cpu_id}: An unexpected error occurred: {e})") 62 + 63 + if __name__ == "__main__": 64 + parser = argparse.ArgumentParser(description=desc, 65 + formatter_class=argparse.RawTextHelpFormatter) 66 + args = parser.parse_args() 67 + 68 + print_root_domains_info()