Skip to content

Commit

Permalink
Merge branch 'printk-rework' into for-linus
Browse files Browse the repository at this point in the history
  • Loading branch information
pmladek committed Oct 12, 2020
2 parents 4e797e6 + 0463d04 commit 70333f4
Show file tree
Hide file tree
Showing 16 changed files with 3,404 additions and 726 deletions.
159 changes: 109 additions & 50 deletions Documentation/admin-guide/kdump/gdbmacros.txt
Original file line number Diff line number Diff line change
Expand Up @@ -170,91 +170,150 @@ document trapinfo
address the kernel panicked.
end

define dump_log_idx
set $idx = $arg0
if ($argc > 1)
set $prev_flags = $arg1
define dump_record
set var $desc = $arg0
set var $info = $arg1
if ($argc > 2)
set var $prev_flags = $arg2
else
set $prev_flags = 0
set var $prev_flags = 0
end
set $msg = ((struct printk_log *) (log_buf + $idx))
set $prefix = 1
set $newline = 1
set $log = log_buf + $idx + sizeof(*$msg)

# prev & LOG_CONT && !(msg->flags & LOG_PREIX)
if (($prev_flags & 8) && !($msg->flags & 4))
set $prefix = 0

set var $prefix = 1
set var $newline = 1

set var $begin = $desc->text_blk_lpos.begin % (1U << prb->text_data_ring.size_bits)
set var $next = $desc->text_blk_lpos.next % (1U << prb->text_data_ring.size_bits)

# handle data-less record
if ($begin & 1)
set var $text_len = 0
set var $log = ""
else
# handle wrapping data block
if ($begin > $next)
set var $begin = 0
end

# skip over descriptor id
set var $begin = $begin + sizeof(long)

# handle truncated message
if ($next - $begin < $info->text_len)
set var $text_len = $next - $begin
else
set var $text_len = $info->text_len
end

set var $log = &prb->text_data_ring.data[$begin]
end

# prev & LOG_CONT && !(info->flags & LOG_PREIX)
if (($prev_flags & 8) && !($info->flags & 4))
set var $prefix = 0
end

# msg->flags & LOG_CONT
if ($msg->flags & 8)
# info->flags & LOG_CONT
if ($info->flags & 8)
# (prev & LOG_CONT && !(prev & LOG_NEWLINE))
if (($prev_flags & 8) && !($prev_flags & 2))
set $prefix = 0
set var $prefix = 0
end
# (!(msg->flags & LOG_NEWLINE))
if (!($msg->flags & 2))
set $newline = 0
# (!(info->flags & LOG_NEWLINE))
if (!($info->flags & 2))
set var $newline = 0
end
end

if ($prefix)
printf "[%5lu.%06lu] ", $msg->ts_nsec / 1000000000, $msg->ts_nsec % 1000000000
printf "[%5lu.%06lu] ", $info->ts_nsec / 1000000000, $info->ts_nsec % 1000000000
end
if ($msg->text_len != 0)
eval "printf \"%%%d.%ds\", $log", $msg->text_len, $msg->text_len
if ($text_len)
eval "printf \"%%%d.%ds\", $log", $text_len, $text_len
end
if ($newline)
printf "\n"
end
if ($msg->dict_len > 0)
set $dict = $log + $msg->text_len
set $idx = 0
set $line = 1
while ($idx < $msg->dict_len)
if ($line)
printf " "
set $line = 0

# handle dictionary data

set var $dict = &$info->dev_info.subsystem[0]
set var $dict_len = sizeof($info->dev_info.subsystem)
if ($dict[0] != '\0')
printf " SUBSYSTEM="
set var $idx = 0
while ($idx < $dict_len)
set var $c = $dict[$idx]
if ($c == '\0')
loop_break
else
if ($c < ' ' || $c >= 127 || $c == '\\')
printf "\\x%02x", $c
else
printf "%c", $c
end
end
set $c = $dict[$idx]
set var $idx = $idx + 1
end
printf "\n"
end

set var $dict = &$info->dev_info.device[0]
set var $dict_len = sizeof($info->dev_info.device)
if ($dict[0] != '\0')
printf " DEVICE="
set var $idx = 0
while ($idx < $dict_len)
set var $c = $dict[$idx]
if ($c == '\0')
printf "\n"
set $line = 1
loop_break
else
if ($c < ' ' || $c >= 127 || $c == '\\')
printf "\\x%02x", $c
else
printf "%c", $c
end
end
set $idx = $idx + 1
set var $idx = $idx + 1
end
printf "\n"
end
end
document dump_log_idx
Dump a single log given its index in the log buffer. The first
parameter is the index into log_buf, the second is optional and
specified the previous log buffer's flags, used for properly
formatting continued lines.
document dump_record
Dump a single record. The first parameter is the descriptor,
the second parameter is the info, the third parameter is
optional and specifies the previous record's flags, used for
properly formatting continued lines.
end

define dmesg
set $i = log_first_idx
set $end_idx = log_first_idx
set $prev_flags = 0
# definitions from kernel/printk/printk_ringbuffer.h
set var $desc_committed = 1
set var $desc_finalized = 2
set var $desc_sv_bits = sizeof(long) * 8
set var $desc_flags_shift = $desc_sv_bits - 2
set var $desc_flags_mask = 3 << $desc_flags_shift
set var $id_mask = ~$desc_flags_mask

set var $desc_count = 1U << prb->desc_ring.count_bits
set var $prev_flags = 0

set var $id = prb->desc_ring.tail_id.counter
set var $end_id = prb->desc_ring.head_id.counter

while (1)
set $msg = ((struct printk_log *) (log_buf + $i))
if ($msg->len == 0)
set $i = 0
else
dump_log_idx $i $prev_flags
set $i = $i + $msg->len
set $prev_flags = $msg->flags
set var $desc = &prb->desc_ring.descs[$id % $desc_count]
set var $info = &prb->desc_ring.infos[$id % $desc_count]

# skip non-committed record
set var $state = 3 & ($desc->state_var.counter >> $desc_flags_shift)
if ($state == $desc_committed || $state == $desc_finalized)
dump_record $desc $info $prev_flags
set var $prev_flags = $info->flags
end
if ($i == $end_idx)

set var $id = ($id + 1) & $id_mask
if ($id == $end_id)
loop_break
end
end
Expand Down
131 changes: 102 additions & 29 deletions Documentation/admin-guide/kdump/vmcoreinfo.rst
Original file line number Diff line number Diff line change
Expand Up @@ -189,50 +189,123 @@ from this.
Free areas descriptor. User-space tools use this value to iterate the
free_area ranges. MAX_ORDER is used by the zone buddy allocator.

log_first_idx
prb
---

A pointer to the printk ringbuffer (struct printk_ringbuffer). This
may be pointing to the static boot ringbuffer or the dynamically
allocated ringbuffer, depending on when the the core dump occurred.
Used by user-space tools to read the active kernel log buffer.

printk_rb_static
----------------

A pointer to the static boot printk ringbuffer. If @prb has a
different value, this is useful for viewing the initial boot messages,
which may have been overwritten in the dynamically allocated
ringbuffer.

clear_seq
---------

The sequence number of the printk() record after the last clear
command. It indicates the first record after the last
SYSLOG_ACTION_CLEAR, like issued by 'dmesg -c'. Used by user-space
tools to dump a subset of the dmesg log.

printk_ringbuffer
-----------------

The size of a printk_ringbuffer structure. This structure contains all
information required for accessing the various components of the
kernel log buffer.

(printk_ringbuffer, desc_ring|text_data_ring|dict_data_ring|fail)
-----------------------------------------------------------------

Offsets for the various components of the printk ringbuffer. Used by
user-space tools to view the kernel log buffer without requiring the
declaration of the structure.

prb_desc_ring
-------------

Index of the first record stored in the buffer log_buf. Used by
user-space tools to read the strings in the log_buf.
The size of the prb_desc_ring structure. This structure contains
information about the set of record descriptors.

log_buf
-------
(prb_desc_ring, count_bits|descs|head_id|tail_id)
-------------------------------------------------

Offsets for the fields describing the set of record descriptors. Used
by user-space tools to be able to traverse the descriptors without
requiring the declaration of the structure.

prb_desc
--------

The size of the prb_desc structure. This structure contains
information about a single record descriptor.

(prb_desc, info|state_var|text_blk_lpos|dict_blk_lpos)
------------------------------------------------------

Offsets for the fields describing a record descriptors. Used by
user-space tools to be able to read descriptors without requiring
the declaration of the structure.

prb_data_blk_lpos
-----------------

The size of the prb_data_blk_lpos structure. This structure contains
information about where the text or dictionary data (data block) is
located within the respective data ring.

(prb_data_blk_lpos, begin|next)
-------------------------------

Console output is written to the ring buffer log_buf at index
log_first_idx. Used to get the kernel log.
Offsets for the fields describing the location of a data block. Used
by user-space tools to be able to locate data blocks without
requiring the declaration of the structure.

log_buf_len
printk_info
-----------

log_buf's length.
The size of the printk_info structure. This structure contains all
the meta-data for a record.

clear_idx
---------
(printk_info, seq|ts_nsec|text_len|dict_len|caller_id)
------------------------------------------------------

The index that the next printk() record to read after the last clear
command. It indicates the first record after the last SYSLOG_ACTION
_CLEAR, like issued by 'dmesg -c'. Used by user-space tools to dump
the dmesg log.
Offsets for the fields providing the meta-data for a record. Used by
user-space tools to be able to read the information without requiring
the declaration of the structure.

log_next_idx
------------
prb_data_ring
-------------

The index of the next record to store in the buffer log_buf. Used to
compute the index of the current buffer position.
The size of the prb_data_ring structure. This structure contains
information about a set of data blocks.

printk_log
----------
(prb_data_ring, size_bits|data|head_lpos|tail_lpos)
---------------------------------------------------

The size of a structure printk_log. Used to compute the size of
messages, and extract dmesg log. It encapsulates header information for
log_buf, such as timestamp, syslog level, etc.
Offsets for the fields describing a set of data blocks. Used by
user-space tools to be able to access the data blocks without
requiring the declaration of the structure.

(printk_log, ts_nsec|len|text_len|dict_len)
-------------------------------------------
atomic_long_t
-------------

The size of the atomic_long_t structure. Used by user-space tools to
be able to copy the full structure, regardless of its
architecture-specific implementation.

(atomic_long_t, counter)
------------------------

It represents field offsets in struct printk_log. User space tools
parse it and check whether the values of printk_log's members have been
changed.
Offset for the long value of an atomic_long_t variable. Used by
user-space tools to access the long value without requiring the
architecture-specific declaration.

(free_area.free_list, MIGRATE_TYPES)
------------------------------------
Expand Down
1 change: 1 addition & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -13838,6 +13838,7 @@ PRINTK
M: Petr Mladek <[email protected]>
M: Sergey Senozhatsky <[email protected]>
R: Steven Rostedt <[email protected]>
R: John Ogness <[email protected]>
S: Maintained
F: include/linux/printk.h
F: kernel/printk/
Expand Down
Loading

0 comments on commit 70333f4

Please sign in to comment.