-
Notifications
You must be signed in to change notification settings - Fork 1
/
README
186 lines (126 loc) · 4.87 KB
/
README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
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>