cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

timerlist.py (7731B)


      1# SPDX-License-Identifier: GPL-2.0
      2#
      3# Copyright 2019 Google LLC.
      4
      5import binascii
      6import gdb
      7
      8from linux import constants
      9from linux import cpus
     10from linux import rbtree
     11from linux import utils
     12
     13timerqueue_node_type = utils.CachedType("struct timerqueue_node").get_type()
     14hrtimer_type = utils.CachedType("struct hrtimer").get_type()
     15
     16
     17def ktime_get():
     18    """Returns the current time, but not very accurately
     19
     20    We can't read the hardware timer itself to add any nanoseconds
     21    that need to be added since we last stored the time in the
     22    timekeeper. But this is probably good enough for debug purposes."""
     23    tk_core = gdb.parse_and_eval("&tk_core")
     24
     25    return tk_core['timekeeper']['tkr_mono']['base']
     26
     27
     28def print_timer(rb_node, idx):
     29    timerqueue = utils.container_of(rb_node, timerqueue_node_type.pointer(),
     30                                    "node")
     31    timer = utils.container_of(timerqueue, hrtimer_type.pointer(), "node")
     32
     33    function = str(timer['function']).split(" ")[1].strip("<>")
     34    softexpires = timer['_softexpires']
     35    expires = timer['node']['expires']
     36    now = ktime_get()
     37
     38    text = " #{}: <{}>, {}, ".format(idx, timer, function)
     39    text += "S:{:02x}\n".format(int(timer['state']))
     40    text += " # expires at {}-{} nsecs [in {} to {} nsecs]\n".format(
     41            softexpires, expires, softexpires - now, expires - now)
     42    return text
     43
     44
     45def print_active_timers(base):
     46    curr = base['active']['next']['node']
     47    curr = curr.address.cast(rbtree.rb_node_type.get_type().pointer())
     48    idx = 0
     49    while curr:
     50        yield print_timer(curr, idx)
     51        curr = rbtree.rb_next(curr)
     52        idx += 1
     53
     54
     55def print_base(base):
     56    text = " .base:       {}\n".format(base.address)
     57    text += " .index:      {}\n".format(base['index'])
     58
     59    text += " .resolution: {} nsecs\n".format(constants.LX_hrtimer_resolution)
     60
     61    text += " .get_time:   {}\n".format(base['get_time'])
     62    if constants.LX_CONFIG_HIGH_RES_TIMERS:
     63        text += "  .offset:     {} nsecs\n".format(base['offset'])
     64    text += "active timers:\n"
     65    text += "".join([x for x in print_active_timers(base)])
     66    return text
     67
     68
     69def print_cpu(hrtimer_bases, cpu, max_clock_bases):
     70    cpu_base = cpus.per_cpu(hrtimer_bases, cpu)
     71    jiffies = gdb.parse_and_eval("jiffies_64")
     72    tick_sched_ptr = gdb.parse_and_eval("&tick_cpu_sched")
     73    ts = cpus.per_cpu(tick_sched_ptr, cpu)
     74
     75    text = "cpu: {}\n".format(cpu)
     76    for i in xrange(max_clock_bases):
     77        text += " clock {}:\n".format(i)
     78        text += print_base(cpu_base['clock_base'][i])
     79
     80        if constants.LX_CONFIG_HIGH_RES_TIMERS:
     81            fmts = [("  .{}   : {} nsecs", 'expires_next'),
     82                    ("  .{}    : {}", 'hres_active'),
     83                    ("  .{}      : {}", 'nr_events'),
     84                    ("  .{}     : {}", 'nr_retries'),
     85                    ("  .{}       : {}", 'nr_hangs'),
     86                    ("  .{}  : {}", 'max_hang_time')]
     87            text += "\n".join([s.format(f, cpu_base[f]) for s, f in fmts])
     88            text += "\n"
     89
     90        if constants.LX_CONFIG_TICK_ONESHOT:
     91            fmts = [("  .{}      : {}", 'nohz_mode'),
     92                    ("  .{}      : {} nsecs", 'last_tick'),
     93                    ("  .{}   : {}", 'tick_stopped'),
     94                    ("  .{}   : {}", 'idle_jiffies'),
     95                    ("  .{}     : {}", 'idle_calls'),
     96                    ("  .{}    : {}", 'idle_sleeps'),
     97                    ("  .{} : {} nsecs", 'idle_entrytime'),
     98                    ("  .{}  : {} nsecs", 'idle_waketime'),
     99                    ("  .{}  : {} nsecs", 'idle_exittime'),
    100                    ("  .{} : {} nsecs", 'idle_sleeptime'),
    101                    ("  .{}: {} nsecs", 'iowait_sleeptime'),
    102                    ("  .{}   : {}", 'last_jiffies'),
    103                    ("  .{}     : {}", 'next_timer'),
    104                    ("  .{}   : {} nsecs", 'idle_expires')]
    105            text += "\n".join([s.format(f, ts[f]) for s, f in fmts])
    106            text += "\njiffies: {}\n".format(jiffies)
    107
    108        text += "\n"
    109
    110    return text
    111
    112
    113def print_tickdevice(td, cpu):
    114    dev = td['evtdev']
    115    text = "Tick Device: mode:     {}\n".format(td['mode'])
    116    if cpu < 0:
    117            text += "Broadcast device\n"
    118    else:
    119            text += "Per CPU device: {}\n".format(cpu)
    120
    121    text += "Clock Event Device: "
    122    if dev == 0:
    123            text += "<NULL>\n"
    124            return text
    125
    126    text += "{}\n".format(dev['name'])
    127    text += " max_delta_ns:   {}\n".format(dev['max_delta_ns'])
    128    text += " min_delta_ns:   {}\n".format(dev['min_delta_ns'])
    129    text += " mult:           {}\n".format(dev['mult'])
    130    text += " shift:          {}\n".format(dev['shift'])
    131    text += " mode:           {}\n".format(dev['state_use_accessors'])
    132    text += " next_event:     {} nsecs\n".format(dev['next_event'])
    133
    134    text += " set_next_event: {}\n".format(dev['set_next_event'])
    135
    136    members = [('set_state_shutdown', " shutdown: {}\n"),
    137               ('set_state_periodic', " periodic: {}\n"),
    138               ('set_state_oneshot', " oneshot:  {}\n"),
    139               ('set_state_oneshot_stopped', " oneshot stopped: {}\n"),
    140               ('tick_resume', " resume:   {}\n")]
    141    for member, fmt in members:
    142        if dev[member]:
    143            text += fmt.format(dev[member])
    144
    145    text += " event_handler:  {}\n".format(dev['event_handler'])
    146    text += " retries:        {}\n".format(dev['retries'])
    147
    148    return text
    149
    150
    151def pr_cpumask(mask):
    152    nr_cpu_ids = 1
    153    if constants.LX_NR_CPUS > 1:
    154        nr_cpu_ids = gdb.parse_and_eval("nr_cpu_ids")
    155
    156    inf = gdb.inferiors()[0]
    157    bits = mask['bits']
    158    num_bytes = (nr_cpu_ids + 7) / 8
    159    buf = utils.read_memoryview(inf, bits, num_bytes).tobytes()
    160    buf = binascii.b2a_hex(buf)
    161
    162    chunks = []
    163    i = num_bytes
    164    while i > 0:
    165        i -= 1
    166        start = i * 2
    167        end = start + 2
    168        chunks.append(buf[start:end])
    169        if i != 0 and i % 4 == 0:
    170            chunks.append(',')
    171
    172    extra = nr_cpu_ids % 8
    173    if 0 < extra <= 4:
    174        chunks[0] = chunks[0][0]  # Cut off the first 0
    175
    176    return "".join(chunks)
    177
    178
    179class LxTimerList(gdb.Command):
    180    """Print /proc/timer_list"""
    181
    182    def __init__(self):
    183        super(LxTimerList, self).__init__("lx-timerlist", gdb.COMMAND_DATA)
    184
    185    def invoke(self, arg, from_tty):
    186        hrtimer_bases = gdb.parse_and_eval("&hrtimer_bases")
    187        max_clock_bases = gdb.parse_and_eval("HRTIMER_MAX_CLOCK_BASES")
    188
    189        text = "Timer List Version: gdb scripts\n"
    190        text += "HRTIMER_MAX_CLOCK_BASES: {}\n".format(max_clock_bases)
    191        text += "now at {} nsecs\n".format(ktime_get())
    192
    193        for cpu in cpus.each_online_cpu():
    194            text += print_cpu(hrtimer_bases, cpu, max_clock_bases)
    195
    196        if constants.LX_CONFIG_GENERIC_CLOCKEVENTS:
    197            if constants.LX_CONFIG_GENERIC_CLOCKEVENTS_BROADCAST:
    198                bc_dev = gdb.parse_and_eval("&tick_broadcast_device")
    199                text += print_tickdevice(bc_dev, -1)
    200                text += "\n"
    201                mask = gdb.parse_and_eval("tick_broadcast_mask")
    202                mask = pr_cpumask(mask)
    203                text += "tick_broadcast_mask: {}\n".format(mask)
    204                if constants.LX_CONFIG_TICK_ONESHOT:
    205                    mask = gdb.parse_and_eval("tick_broadcast_oneshot_mask")
    206                    mask = pr_cpumask(mask)
    207                    text += "tick_broadcast_oneshot_mask: {}\n".format(mask)
    208                text += "\n"
    209
    210            tick_cpu_devices = gdb.parse_and_eval("&tick_cpu_device")
    211            for cpu in cpus.each_online_cpu():
    212                tick_dev = cpus.per_cpu(tick_cpu_devices, cpu)
    213                text += print_tickdevice(tick_dev, cpu)
    214                text += "\n"
    215
    216        gdb.write(text)
    217
    218
    219LxTimerList()