Re: [PATCH 1/3] docs: s390: restore important non-kdoc parts of s390dbf.rst

From: Christian Borntraeger
Date: Fri Jul 05 2019 - 06:53:24 EST




On 03.07.19 12:19, Steffen Maier wrote:
> Complements previous ("s390: include/asm/debug.h add kerneldoc markups")
> which seemed to have dropped important non-kdoc parts such as
> user space interface (level, size, flush)
> as well as views and caution regarding strings in the sprintf view.
>
> Signed-off-by: Steffen Maier <maier@xxxxxxxxxxxxx>

Acked-by: Christian Borntraeger <borntraeger@xxxxxxxxxx>

> ---
> Documentation/s390/s390dbf.rst | 339 +++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 339 insertions(+)
>
> diff --git a/Documentation/s390/s390dbf.rst b/Documentation/s390/s390dbf.rst
> index d2595b548879..01d66251643d 100644
> --- a/Documentation/s390/s390dbf.rst
> +++ b/Documentation/s390/s390dbf.rst
> @@ -112,6 +112,345 @@ Kernel Interfaces:
> Predefined views:
> -----------------
>
> +extern struct debug_view debug_hex_ascii_view;
> +
> +extern struct debug_view debug_raw_view;
> +
> +extern struct debug_view debug_sprintf_view;
> +
> +Examples
> +--------
> +
> +::
> +
> + /*
> + * hex_ascii- + raw-view Example
> + */
> +
> + #include <linux/init.h>
> + #include <asm/debug.h>
> +
> + static debug_info_t* debug_info;
> +
> + static int init(void)
> + {
> + /* register 4 debug areas with one page each and 4 byte data field */
> +
> + debug_info = debug_register ("test", 1, 4, 4 );
> + debug_register_view(debug_info,&debug_hex_ascii_view);
> + debug_register_view(debug_info,&debug_raw_view);
> +
> + debug_text_event(debug_info, 4 , "one ");
> + debug_int_exception(debug_info, 4, 4711);
> + debug_event(debug_info, 3, &debug_info, 4);
> +
> + return 0;
> + }
> +
> + static void cleanup(void)
> + {
> + debug_unregister (debug_info);
> + }
> +
> + module_init(init);
> + module_exit(cleanup);
> +
> +::
> +
> + /*
> + * sprintf-view Example
> + */
> +
> + #include <linux/init.h>
> + #include <asm/debug.h>
> +
> + static debug_info_t* debug_info;
> +
> + static int init(void)
> + {
> + /* register 4 debug areas with one page each and data field for */
> + /* format string pointer + 2 varargs (= 3 * sizeof(long)) */
> +
> + debug_info = debug_register ("test", 1, 4, sizeof(long) * 3);
> + debug_register_view(debug_info,&debug_sprintf_view);
> +
> + debug_sprintf_event(debug_info, 2 , "first event in %s:%i\n",__FILE__,__LINE__);
> + debug_sprintf_exception(debug_info, 1, "pointer to debug info: %p\n",&debug_info);
> +
> + return 0;
> + }
> +
> + static void cleanup(void)
> + {
> + debug_unregister (debug_info);
> + }
> +
> + module_init(init);
> + module_exit(cleanup);
> +
> +Debugfs Interface
> +-----------------
> +Views to the debug logs can be investigated through reading the corresponding
> +debugfs-files:
> +
> +Example::
> +
> + > ls /sys/kernel/debug/s390dbf/dasd
> + flush hex_ascii level pages raw
> + > cat /sys/kernel/debug/s390dbf/dasd/hex_ascii | sort -k2,2 -s
> + 00 00974733272:680099 2 - 02 0006ad7e 07 ea 4a 90 | ....
> + 00 00974733272:682210 2 - 02 0006ade6 46 52 45 45 | FREE
> + 00 00974733272:682213 2 - 02 0006adf6 07 ea 4a 90 | ....
> + 00 00974733272:682281 1 * 02 0006ab08 41 4c 4c 43 | EXCP
> + 01 00974733272:682284 2 - 02 0006ab16 45 43 4b 44 | ECKD
> + 01 00974733272:682287 2 - 02 0006ab28 00 00 00 04 | ....
> + 01 00974733272:682289 2 - 02 0006ab3e 00 00 00 20 | ...
> + 01 00974733272:682297 2 - 02 0006ad7e 07 ea 4a 90 | ....
> + 01 00974733272:684384 2 - 00 0006ade6 46 52 45 45 | FREE
> + 01 00974733272:684388 2 - 00 0006adf6 07 ea 4a 90 | ....
> +
> +See section about predefined views for explanation of the above output!
> +
> +Changing the debug level
> +------------------------
> +
> +Example::
> +
> +
> + > cat /sys/kernel/debug/s390dbf/dasd/level
> + 3
> + > echo "5" > /sys/kernel/debug/s390dbf/dasd/level
> + > cat /sys/kernel/debug/s390dbf/dasd/level
> + 5
> +
> +Flushing debug areas
> +--------------------
> +Debug areas can be flushed with piping the number of the desired
> +area (0...n) to the debugfs file "flush". When using "-" all debug areas
> +are flushed.
> +
> +Examples:
> +
> +1. Flush debug area 0::
> +
> + > echo "0" > /sys/kernel/debug/s390dbf/dasd/flush
> +
> +2. Flush all debug areas::
> +
> + > echo "-" > /sys/kernel/debug/s390dbf/dasd/flush
> +
> +Changing the size of debug areas
> +------------------------------------
> +It is possible the change the size of debug areas through piping
> +the number of pages to the debugfs file "pages". The resize request will
> +also flush the debug areas.
> +
> +Example:
> +
> +Define 4 pages for the debug areas of debug feature "dasd"::
> +
> + > echo "4" > /sys/kernel/debug/s390dbf/dasd/pages
> +
> +Stooping the debug feature
> +--------------------------
> +Example:
> +
> +1. Check if stopping is allowed::
> +
> + > cat /proc/sys/s390dbf/debug_stoppable
> +
> +2. Stop debug feature::
> +
> + > echo 0 > /proc/sys/s390dbf/debug_active
> +
> +lcrash Interface
> +----------------
> +It is planned that the dump analysis tool lcrash gets an additional command
> +'s390dbf' to display all the debug logs. With this tool it will be possible
> +to investigate the debug logs on a live system and with a memory dump after
> +a system crash.
> +
> +Investigating raw memory
> +------------------------
> +One last possibility to investigate the debug logs at a live
> +system and after a system crash is to look at the raw memory
> +under VM or at the Service Element.
> +It is possible to find the anker of the debug-logs through
> +the 'debug_area_first' symbol in the System map. Then one has
> +to follow the correct pointers of the data-structures defined
> +in debug.h and find the debug-areas in memory.
> +Normally modules which use the debug feature will also have
> +a global variable with the pointer to the debug-logs. Following
> +this pointer it will also be possible to find the debug logs in
> +memory.
> +
> +For this method it is recommended to use '16 * x + 4' byte (x = 0..n)
> +for the length of the data field in debug_register() in
> +order to see the debug entries well formatted.
> +
> +
> +Predefined Views
> +----------------
> +
> +There are three predefined views: hex_ascii, raw and sprintf.
> +The hex_ascii view shows the data field in hex and ascii representation
> +(e.g. '45 43 4b 44 | ECKD').
> +The raw view returns a bytestream as the debug areas are stored in memory.
> +
> +The sprintf view formats the debug entries in the same way as the sprintf
> +function would do. The sprintf event/exception functions write to the
> +debug entry a pointer to the format string (size = sizeof(long))
> +and for each vararg a long value. So e.g. for a debug entry with a format
> +string plus two varargs one would need to allocate a (3 * sizeof(long))
> +byte data area in the debug_register() function.
> +
> +IMPORTANT:
> + Using "%s" in sprintf event functions is dangerous. You can only
> + use "%s" in the sprintf event functions, if the memory for the passed string
> + is available as long as the debug feature exists. The reason behind this is
> + that due to performance considerations only a pointer to the string is stored
> + in the debug feature. If you log a string that is freed afterwards, you will
> + get an OOPS when inspecting the debug feature, because then the debug feature
> + will access the already freed memory.
> +
> +NOTE:
> + If using the sprintf view do NOT use other event/exception functions
> + than the sprintf-event and -exception functions.
> +
> +The format of the hex_ascii and sprintf view is as follows:
> +
> +- Number of area
> +- Timestamp (formatted as seconds and microseconds since 00:00:00 Coordinated
> + Universal Time (UTC), January 1, 1970)
> +- level of debug entry
> +- Exception flag (* = Exception)
> +- Cpu-Number of calling task
> +- Return Address to caller
> +- data field
> +
> +The format of the raw view is:
> +
> +- Header as described in debug.h
> +- datafield
> +
> +A typical line of the hex_ascii view will look like the following (first line
> +is only for explanation and will not be displayed when 'cating' the view):
> +
> +area time level exception cpu caller data (hex + ascii)
> +--------------------------------------------------------------------------
> +00 00964419409:440690 1 - 00 88023fe
> +
> +
> +Defining views
> +--------------
> +
> +Views are specified with the 'debug_view' structure. There are defined
> +callback functions which are used for reading and writing the debugfs files::
> +
> + struct debug_view {
> + char name[DEBUG_MAX_PROCF_LEN];
> + debug_prolog_proc_t* prolog_proc;
> + debug_header_proc_t* header_proc;
> + debug_format_proc_t* format_proc;
> + debug_input_proc_t* input_proc;
> + void* private_data;
> + };
> +
> +where::
> +
> + typedef int (debug_header_proc_t) (debug_info_t* id,
> + struct debug_view* view,
> + int area,
> + debug_entry_t* entry,
> + char* out_buf);
> +
> + typedef int (debug_format_proc_t) (debug_info_t* id,
> + struct debug_view* view, char* out_buf,
> + const char* in_buf);
> + typedef int (debug_prolog_proc_t) (debug_info_t* id,
> + struct debug_view* view,
> + char* out_buf);
> + typedef int (debug_input_proc_t) (debug_info_t* id,
> + struct debug_view* view,
> + struct file* file, const char* user_buf,
> + size_t in_buf_size, loff_t* offset);
> +
> +
> +The "private_data" member can be used as pointer to view specific data.
> +It is not used by the debug feature itself.
> +
> +The output when reading a debugfs file is structured like this::
> +
> + "prolog_proc output"
> +
> + "header_proc output 1" "format_proc output 1"
> + "header_proc output 2" "format_proc output 2"
> + "header_proc output 3" "format_proc output 3"
> + ...
> +
> +When a view is read from the debugfs, the Debug Feature calls the
> +'prolog_proc' once for writing the prolog.
> +Then 'header_proc' and 'format_proc' are called for each
> +existing debug entry.
> +
> +The input_proc can be used to implement functionality when it is written to
> +the view (e.g. like with 'echo "0" > /sys/kernel/debug/s390dbf/dasd/level).
> +
> +For header_proc there can be used the default function
> +debug_dflt_header_fn() which is defined in debug.h.
> +and which produces the same header output as the predefined views.
> +E.g::
> +
> + 00 00964419409:440761 2 - 00 88023ec
> +
> +In order to see how to use the callback functions check the implementation
> +of the default views!
> +
> +Example::
> +
> + #include <asm/debug.h>
> +
> + #define UNKNOWNSTR "data: %08x"
> +
> + const char* messages[] =
> + {"This error...........\n",
> + "That error...........\n",
> + "Problem..............\n",
> + "Something went wrong.\n",
> + "Everything ok........\n",
> + NULL
> + };
> +
> + static int debug_test_format_fn(
> + debug_info_t * id, struct debug_view *view,
> + char *out_buf, const char *in_buf
> + )
> + {
> + int i, rc = 0;
> +
> + if(id->buf_size >= 4) {
> + int msg_nr = *((int*)in_buf);
> + if(msg_nr < sizeof(messages)/sizeof(char*) - 1)
> + rc += sprintf(out_buf, "%s", messages[msg_nr]);
> + else
> + rc += sprintf(out_buf, UNKNOWNSTR, msg_nr);
> + }
> + out:
> + return rc;
> + }
> +
> + struct debug_view debug_test_view = {
> + "myview", /* name of view */
> + NULL, /* no prolog */
> + &debug_dflt_header_fn, /* default header for each entry */
> + &debug_test_format_fn, /* our own format function */
> + NULL, /* no input function */
> + NULL /* no private data */
> + };
> +
> +test:
> +=====
> +
> ::
>
> debug_info_t *debug_info;
>