Skip to content

krytarowski/debugcon_printf

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

debugcon_printf for NetBSD

This is a NetBSD specific loadable kernel module that implements a standalone
printing mechanism to Bochs/Qemu-style debug console (port 0xe9).

Prerequisites
=============

 * NetBSD distribution preinstalled with kernel sources (src/sys)

 * NetBSD/amd64 kernel tested (i386 should work)

Building
========

Steps:

1. Fetch the sources of debugcon_printf.
2. Fetch the NetBSD kernel sources in the same version as your running kernel.
3. If the kernel sources are in a custom location, pass it with BSDSRCDIR.
4. Run make(1) and build the sources of the kernel module:

$ make # BSDSRCDIR=/usr/src

Testing
=======

Testing is performed in user-space. The 'test' target builds two versions
of test.c: with debugconf_printf() compiled in userland and printf(3) from
libc. As a validation outputs from both functions are compared.

In order to run tests, invoke:

$ make test

Files
=====

debugcon_printf.kmod - loadable kernel module for the NetBSD kernel
debugcon_printf.h    - kernel header with the prototype of debugconf_printf()

Usage
=====

Start Qemu with extra arguments for debugcon and optionally specifying port:

-debugcon dev
    Redirect the debug console to host device dev (same devices as the serial
    port).  The debug console is an I/O port which is typically port 0xe9;
    writing to that I/O port sends output to this device. The default device is
    "vc" in graphical mode and "stdio" in non graphical mode.

The debug console port can be specified with:

  -global isa-debugcon.iobase=0xe9

As root:

  # modload -i iobase=233 ./debugcon_printf.kmod # 233=0xe9

NB. The argument passed to -i as of NetBSD 8.99.42 must be decimal.

Include the debugcon_printf header in your code:

  #include <debugcon_printf.h> /* or "debugcon_printf.h" */

Print "hello world" in your code:

  debugcon_printf("Hello world!\n");

Example
=======

1. Start a NetBSD Qemu guest with:

$ qemu-system-x86_64 \
	...
	-debugcon file:/tmp/qemu.debug.log -global isa-debugcon.iobase=0xe9 \
	...

2. Fetch debugcon_printf repository.

3. Build debugconf_printf and insert into the kernel.

$ make
$ modload ./debugcon_printf.kmod

4. Build example/ and insert into the kernel.

$ cd example
$ modload ./example.kmod

5. Read the Qemu debug log file.

$ cat /tmp/qemu.debug.log | head
Hello world
'My string_12345'
'                                                                                     My string_12345'
'My string_12345                                                                                     '
	'Tab.'
'%'
'X'
'88'
'2'
'3'

Use-cases
=========

Ad-hoc outputing debug text without patching the NetBSD kernel code.

The debugging console is specific to an emulator (Bochs and Qemu) and it uses
CPU specific code ("outb" instruction). Why to not merge this into mainline
kernel code? This implementation is CPU specific and the code is shared with
rumpkernels that shall not run privileged instructions. The main motivation
here is to output log to an external console out of the guest machine, without
triggering sanitizers or code coverage functions, what would be difficult to
achieve with using generic kernel code stack.

Printing to debug console allows to gather track of enormous kernel trace
logs for gigabytes of data. Traditional mechanisms like dmesg(8) are highly
restricted to small buffers and are not always suitable to see the full
log of booting messages.

Supported syntax
================

debugcon_printf() supports the subset of the standard ANSI printf(3) syntax.

%[MODIFIERS][WIDTH][TYPE_MODIFIERS][TYPE]

Supported modifiers:

 - '#' Print character with alternative form (supported for numbers only).
 - '-' Left adjustment (supported for strings only).
 - '+' Print leading '+' character for signed positive numbers.
 - ' ' Print leading ' ' character for signed positive numbers.
 - '0' Print number with leading zeros padding.

Field width is a decimal number (supported for strings only).

Supported type modifiers:
 - 'l' long
 - 'll' long long
 - 'h' short
 - 'hh' short short (char)
 - 'z' size_t type (mapped to long)

Supported types:

 - 's' string (char *)
 - 'c' character
 - 'd' signed integer
 - 'u' unsigned integer
 - 'x' hex number
 - 'o' oct number

'%%' is printed as '%'.

Implementation details
======================

The kernel module is implemented in a single C file debugcon_printf.c with
a header for external users debugcon_printf.h.

The debugcon_printf() implementation does not call any external system function
libraries. The propose of this design is to be independent from other kernel
routines that could be instrumented with either sanitizer or code coverage.

Porting notes
=============

The code in debugcon_printf.c is NetBSD kernel specific.

Expanding support to new CPUs requires porting the internal_putchar() function.
This function implements I/O port byte write.

License
=======

BSD 2-clause.

Author
======

Kamil Rytarowski <kamil @ NetBSD . org>

About

Bochs/Qemu debugcon printf() loadable kernel module for NetBSD

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published