@@ -10,7 +10,52 @@ use core::cmp;
10
10
use core:: fmt;
11
11
12
12
use crate :: bindings;
13
- use crate :: c_types:: c_int;
13
+ use crate :: c_types:: { c_char, c_void} ;
14
+
15
+ // Called from `vsprintf` with format specifier `%pA`.
16
+ #[ no_mangle]
17
+ unsafe fn rust_fmt_argument ( buf : * mut c_char , end : * mut c_char , ptr : * const c_void ) -> * mut c_char {
18
+ use fmt:: Write ;
19
+
20
+ // Use `usize` to use `saturating_*` functions.
21
+ struct Writer {
22
+ buf : usize ,
23
+ end : usize ,
24
+ }
25
+
26
+ impl Write for Writer {
27
+ fn write_str ( & mut self , s : & str ) -> fmt:: Result {
28
+ // `buf` value after writing `len` bytes. This does not have to be bounded
29
+ // by `end`, but we don't want it to wrap around to 0.
30
+ let buf_new = self . buf . saturating_add ( s. len ( ) ) ;
31
+
32
+ // Amount that we can copy. `saturating_sub` ensures we get 0 if
33
+ // `buf` goes past `end`.
34
+ let len_to_copy = cmp:: min ( buf_new, self . end ) . saturating_sub ( self . buf ) ;
35
+
36
+ // SAFETY: In any case, `buf` is non-null and properly aligned.
37
+ // If `len_to_copy` is non-zero, then we know `buf` has not past
38
+ // `end` yet and so is valid.
39
+ unsafe {
40
+ core:: ptr:: copy_nonoverlapping (
41
+ s. as_bytes ( ) . as_ptr ( ) ,
42
+ self . buf as * mut u8 ,
43
+ len_to_copy,
44
+ )
45
+ } ;
46
+
47
+ self . buf = buf_new;
48
+ Ok ( ( ) )
49
+ }
50
+ }
51
+
52
+ let mut w = Writer {
53
+ buf : buf as _ ,
54
+ end : end as _ ,
55
+ } ;
56
+ let _ = w. write_fmt ( * ( ptr as * const fmt:: Arguments < ' _ > ) ) ;
57
+ w. buf as _
58
+ }
14
59
15
60
/// Format strings.
16
61
///
@@ -23,7 +68,7 @@ pub mod format_strings {
23
68
const LENGTH_PREFIX : usize = 2 ;
24
69
25
70
/// The length of the fixed format strings.
26
- pub const LENGTH : usize = 11 ;
71
+ pub const LENGTH : usize = 10 ;
27
72
28
73
/// Generates a fixed format string for the kernel's [`printk`].
29
74
///
@@ -42,14 +87,14 @@ pub mod format_strings {
42
87
assert ! ( prefix[ 2 ] == b'\x00' ) ;
43
88
44
89
let suffix: & [ u8 ; LENGTH - LENGTH_PREFIX ] = if is_cont {
45
- b"%.*s \0 \0 \0 \0 \0 "
90
+ b"%pA \0 \0 \0 \0 \0 "
46
91
} else {
47
- b"%s: %.*s \0 "
92
+ b"%s: %pA \0 "
48
93
} ;
49
94
50
95
[
51
96
prefix[ 0 ] , prefix[ 1 ] , suffix[ 0 ] , suffix[ 1 ] , suffix[ 2 ] , suffix[ 3 ] , suffix[ 4 ] , suffix[ 5 ] ,
52
- suffix[ 6 ] , suffix[ 7 ] , suffix [ 8 ] ,
97
+ suffix[ 6 ] , suffix[ 7 ] ,
53
98
]
54
99
}
55
100
@@ -84,14 +129,13 @@ pub mod format_strings {
84
129
pub unsafe fn call_printk (
85
130
format_string : & [ u8 ; format_strings:: LENGTH ] ,
86
131
module_name : & [ u8 ] ,
87
- string : & [ u8 ] ,
132
+ args : fmt :: Arguments < ' _ > ,
88
133
) {
89
134
// `printk` does not seem to fail in any path.
90
135
bindings:: printk (
91
136
format_string. as_ptr ( ) as _ ,
92
137
module_name. as_ptr ( ) ,
93
- string. len ( ) as c_int ,
94
- string. as_ptr ( ) ,
138
+ & args as * const _ as * const c_void ,
95
139
) ;
96
140
}
97
141
@@ -101,112 +145,26 @@ pub unsafe fn call_printk(
101
145
///
102
146
/// [`printk`]: ../../../../include/linux/printk.h
103
147
#[ doc( hidden) ]
104
- pub fn call_printk_cont ( string : & [ u8 ] ) {
148
+ pub fn call_printk_cont ( args : fmt :: Arguments < ' _ > ) {
105
149
// `printk` does not seem to fail in any path.
106
150
//
107
151
// SAFETY: The format string is fixed.
108
152
unsafe {
109
153
bindings:: printk (
110
154
format_strings:: CONT . as_ptr ( ) as _ ,
111
- string. len ( ) as c_int ,
112
- string. as_ptr ( ) ,
155
+ & args as * const _ as * const c_void ,
113
156
) ;
114
157
}
115
158
}
116
159
117
- /// The maximum size of a log line in the kernel.
118
- ///
119
- /// From `kernel/printk/printk.c`.
120
- const LOG_LINE_MAX : usize = 1024 - 32 ;
121
-
122
- /// The maximum size of a log line in our side.
123
- ///
124
- /// FIXME: We should be smarter than this, but for the moment, to reduce stack
125
- /// usage, we only allow this much which should work for most purposes.
126
- const LOG_LINE_SIZE : usize = 300 ;
127
- crate :: static_assert!( LOG_LINE_SIZE <= LOG_LINE_MAX ) ;
128
-
129
- /// Public but hidden since it should only be used from public macros.
130
- #[ doc( hidden) ]
131
- pub struct LogLineWriter {
132
- data : [ u8 ; LOG_LINE_SIZE ] ,
133
- pos : usize ,
134
- }
135
-
136
- impl LogLineWriter {
137
- /// Creates a new [`LogLineWriter`].
138
- pub fn new ( ) -> LogLineWriter {
139
- LogLineWriter {
140
- data : [ 0u8 ; LOG_LINE_SIZE ] ,
141
- pos : 0 ,
142
- }
143
- }
144
-
145
- /// Returns the internal buffer as a byte slice.
146
- pub fn as_bytes ( & self ) -> & [ u8 ] {
147
- & self . data [ ..self . pos ]
148
- }
149
- }
150
-
151
- impl Default for LogLineWriter {
152
- fn default ( ) -> Self {
153
- Self :: new ( )
154
- }
155
- }
156
-
157
- impl fmt:: Write for LogLineWriter {
158
- fn write_str ( & mut self , s : & str ) -> fmt:: Result {
159
- let copy_len = cmp:: min ( LOG_LINE_SIZE - self . pos , s. as_bytes ( ) . len ( ) ) ;
160
- self . data [ self . pos ..self . pos + copy_len] . copy_from_slice ( & s. as_bytes ( ) [ ..copy_len] ) ;
161
- self . pos += copy_len;
162
- Ok ( ( ) )
163
- }
164
- }
165
-
166
- /// Helper function for the [`print_macro!`] to reduce stack usage.
167
- ///
168
- /// Public but hidden since it should only be used from public macros.
169
- ///
170
- /// # Safety
171
- ///
172
- /// The format string must be one of the ones in [`format_strings`], and
173
- /// the module name must be null-terminated.
174
- #[ doc( hidden) ]
175
- pub unsafe fn format_and_call < const CONT : bool > (
176
- format_string : & [ u8 ; format_strings:: LENGTH ] ,
177
- module_name : & [ u8 ] ,
178
- args : fmt:: Arguments ,
179
- ) {
180
- // Careful: this object takes quite a bit of stack.
181
- let mut writer = LogLineWriter :: new ( ) ;
182
-
183
- match fmt:: write ( & mut writer, args) {
184
- Ok ( _) => {
185
- if CONT {
186
- call_printk_cont ( writer. as_bytes ( ) ) ;
187
- } else {
188
- call_printk ( format_string, module_name, writer. as_bytes ( ) ) ;
189
- }
190
- }
191
-
192
- Err ( _) => {
193
- call_printk (
194
- & format_strings:: CRIT ,
195
- module_name,
196
- b"Failure to format string.\n " ,
197
- ) ;
198
- }
199
- } ;
200
- }
201
-
202
160
/// Performs formatting and forwards the string to [`call_printk`].
203
161
///
204
162
/// Public but hidden since it should only be used from public macros.
205
163
#[ doc( hidden) ]
206
164
#[ macro_export]
207
165
macro_rules! print_macro (
208
- // Without extra arguments: no need to format anything .
209
- ( $format_string: path, false , $fmt : expr ) => (
166
+ // The non-continuation cases (most of them, e.g. `INFO`) .
167
+ ( $format_string: path, false , $( $arg : tt ) + ) => (
210
168
// SAFETY: This hidden macro should only be called by the documented
211
169
// printing macros which ensure the format string is one of the fixed
212
170
// ones. All `__LOG_PREFIX`s are null-terminated as they are generated
@@ -216,47 +174,17 @@ macro_rules! print_macro (
216
174
$crate:: print:: call_printk(
217
175
& $format_string,
218
176
crate :: __LOG_PREFIX,
219
- $fmt . as_bytes ( ) ,
177
+ format_args! ( $ ( $arg ) + ) ,
220
178
) ;
221
179
}
222
180
) ;
223
181
224
- // Without extra arguments: no need to format anything ( `CONT` case) .
225
- ( $format_string: path, true , $fmt : expr ) => (
182
+ // The `CONT` case.
183
+ ( $format_string: path, true , $( $arg : tt ) + ) => (
226
184
$crate:: print:: call_printk_cont(
227
- $fmt . as_bytes ( ) ,
185
+ format_args! ( $ ( $arg ) + ) ,
228
186
) ;
229
187
) ;
230
-
231
- // With extra arguments: we need to perform formatting.
232
- ( $format_string: path, $cont: literal, $fmt: expr, $( $arg: tt) * ) => (
233
- // Forwarding the call to a function to perform the formatting
234
- // is needed here to avoid stack overflows in non-optimized builds when
235
- // invoking the printing macros a lot of times in the same function.
236
- // Without it, the compiler reserves one `LogLineWriter` per macro
237
- // invocation, which is a huge type.
238
- //
239
- // We could use an immediately-invoked closure for this, which
240
- // seems to lower even more the stack usage at `opt-level=0` because
241
- // `fmt::Arguments` objects do not pile up. However, that breaks
242
- // the `?` operator if used in one of the arguments.
243
- //
244
- // At `opt-level=2`, the generated code is basically the same for
245
- // all alternatives.
246
- //
247
- // SAFETY: This hidden macro should only be called by the documented
248
- // printing macros which ensure the format string is one of the fixed
249
- // ones. All `__LOG_PREFIX`s are null-terminated as they are generated
250
- // by the `module!` proc macro or fixed values defined in a kernel
251
- // crate.
252
- unsafe {
253
- $crate:: print:: format_and_call:: <$cont>(
254
- & $format_string,
255
- crate :: __LOG_PREFIX,
256
- format_args!( $fmt, $( $arg) * ) ,
257
- ) ;
258
- }
259
- ) ;
260
188
) ;
261
189
262
190
// We could use a macro to generate these macros. However, doing so ends
0 commit comments