# printk

* [Printk](#printk)
  * [Message logging](#message-logging)
  * [Specifiers](#specifiers)
  * [Printk Index](#printk-index)
  * [Subsystem specific prefix](#subsystem-specific-prefix)
  * [References](#references)

## Printk

* `printk()` is one of the most widely known functions in the Linux kernel
* standard tool we have for printing messages and usually the **most basic way** of tracing and debugging
* All printk() messages are printed to the kernel log buffer, which is a **ring buffer** exported to userspace through `/dev/kmsg`. The usual way to read it is using `dmesg`.

### Message logging

* `printk()` can specify a log level : `printk(KERN_INFO "Message: %s\n", arg);`

| Name          | String | Alias function                                                                                                                                                                        |
| ------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| KERN\_EMERG   | “0”    | [`pr_emerg()`](https://docs.kernel.org/core-api/printk-basics.html#c.pr_emerg)                                                                                                        |
| KERN\_ALERT   | “1”    | [`pr_alert()`](https://docs.kernel.org/core-api/printk-basics.html#c.pr_alert)                                                                                                        |
| KERN\_CRIT    | “2”    | [`pr_crit()`](https://docs.kernel.org/core-api/printk-basics.html#c.pr_crit)                                                                                                          |
| KERN\_ERR     | “3”    | [`pr_err()`](https://docs.kernel.org/core-api/printk-basics.html#c.pr_err)                                                                                                            |
| KERN\_WARNING | “4”    | [`pr_warn()`](https://docs.kernel.org/core-api/printk-basics.html#c.pr_warn)                                                                                                          |
| KERN\_NOTICE  | “5”    | [`pr_notice()`](https://docs.kernel.org/core-api/printk-basics.html#c.pr_notice)                                                                                                      |
| KERN\_INFO    | “6”    | [`pr_info()`](https://docs.kernel.org/core-api/printk-basics.html#c.pr_info)                                                                                                          |
| KERN\_DEBUG   | “7”    | [`pr_debug()`](https://docs.kernel.org/core-api/printk-basics.html#c.pr_debug) and [`pr_devel()`](https://docs.kernel.org/core-api/printk-basics.html#c.pr_devel) if DEBUG is defined |
| KERN\_DEFAULT | “”     |                                                                                                                                                                                       |
| KERN\_CONT    | “c”    | [`pr_cont()`](https://docs.kernel.org/core-api/printk-basics.html#c.pr_cont)                                                                                                          |

* To check the current *console\_loglevel* : (shows *current*, *default*, *minimum* and *boot-time-default* log levels)

```shell
$ cat /proc/sys/kernel/printk
4        4        1        7
```

* This can be changed using `# echo 8 > /proc/sys/kernel/printk` or `# dmesg -n 5`.
* `pr_info`, `pr_debug` are macros that help to print logs at different levels

### Specifiers

There are many print specifiers present, it’s better to check these specifiers before using printk. These are available at : [Printk Formats - Kernel Docs](https://docs.kernel.org/core-api/printk-formats.html).

The common types are :

* Integer Types (signed char, unsigned char, int, unsigned short int, etc.)
* Pointer Types
  * Plain Pointers
  * Error Pointers
  * Symbol/Function Pointers (Eg : `%pS versatile_init+0x0/0x110`)
  * Probe pointers from BPF/tracing
  * Kernel Pointers
  * Unmodified address
  * Pointer Differences
  * Struct Resources
  * Physical addresses (`%pa[p] 0x01234567 or 0x0123456789abcdef`)
  * DMA addresses (`%pad 0x01234567 or 0x0123456789abcdef`)
  * Raw buffer
  * MAC addresses (`%pM 00:01:02:03:04:05`)
  * IPv4/v6 Addresses (`%pI4 1.2.3.4`)
  * UID/GUID (`%pUb 00010203-0405-0607-0809-0a0b0c0d0e0f`)
  * Dentrys (`%pd{,2,3,4}`)
  * And many more …

### Printk Index

> The kernel messages are evolving together with the code. As a result, particular kernel messages are not `KABI` and never will be! (See : [Kernel ABI doc](https://lagnos.gitbook.io/linux-kernel-notes/misc/kabi) for KABI)

* The printk index helps to find changes in the message formats. Also it helps to track the strings back to the kernel sources and the related commit.
* The index of printk formats are split in into separate files.

```
/sys/kernel/debug/printk/index/vmlinux
/sys/kernel/debug/printk/index/ext4
/sys/kernel/debug/printk/index/scsi_mod
```

The content is inspired by the dynamic debug interface and looks like:

```shell
$> head -1 /sys/kernel/debug/printk/index/vmlinux; shuf -n 5 vmlinux
# <level[,flags]> filename:line function "format"
<5> block/blk-settings.c:661 disk_stack_limits "%s: Warning: Device %s is misaligned\n"
<4> kernel/trace/trace.c:8296 trace_create_file "Could not create tracefs '%s' entry\n"
<6> arch/x86/kernel/hpet.c:144 _hpet_print_config "hpet: %s(%d):\n"
<6> init/do_mounts.c:605 prepare_namespace "Waiting for root device %s...\n"
<6> drivers/acpi/osl.c:1410 acpi_no_auto_serialize_setup "ACPI: auto-serialization disabled\n"
```

### Subsystem specific prefix

* The macro `pr_fmt()` macro allows to define a prefix that is printed before the string generated by the related `printk()` calls.

```c
#define pr_fmt(fmt) "ACPI: OSL: " fmt

static int __init acpi_no_auto_serialize_setup(char *str)
{
      acpi_gbl_auto_serialize_methods = FALSE;
      pr_info("Auto-serialization disabled\n");

      return 1;
}
```

This results in the following `printk` index entry:

```
<6> drivers/acpi/osl.c:1410 acpi_no_auto_serialize_setup "ACPI: auto-serialization disabled\n"
```

### References

* [Printk Basics - Kernel Docs](https://docs.kernel.org/core-api/printk-basics.html)
* [Printk Formats - Kernel Docs](https://docs.kernel.org/core-api/printk-formats.html)
* [Printk Index - Kernel Docs](https://docs.kernel.org/core-api/printk-index.html)
