2 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
31 #include <i386/cpu_data.h>
32 #include <i386/bit_routines.h>
33 #include <i386/machine_cpu.h>
34 #include <i386/machine_routines.h>
35 #include <i386/misc_protos.h>
36 #include <i386/serial_io.h>
37 #endif /* __x86_64__ */
39 #include <libkern/OSAtomic.h>
40 #include <vm/vm_kern.h>
41 #include <vm/vm_map.h>
42 #include <console/video_console.h>
43 #include <console/serial_protos.h>
44 #include <kern/kalloc.h>
45 #include <kern/thread.h>
46 #include <kern/cpu_data.h>
47 #include <libkern/section_keywords.h>
52 #define MAX_CPU_SLOTS (MAX_CPUS)
61 decl_simple_lock_data(, read_lock
);
62 decl_simple_lock_data(, write_lock
);
65 hw_lock_data_t cnputc_lock
;
66 static volatile uint32_t console_output
= 0;
69 * New allocation mechanism for console buffers
70 * Total allocation: 1 * PAGE_SIZE
71 * - Each cpu gets CPU_CONS_BUF_SIZE buffer
72 * - Kernel wide console ring gets PAGE_SIZE - MAX_CPU_SLOTS * CPU_CONS_BUF_SIZE
74 * At the return from console_init() the memory is setup as follows:
75 * +----------------------------+-------------+-------------+-------------+-------------+
76 * |console ring buffer---------|f2eec075-----|f2eec075-----|f2eec075-----|f2eec075-----|
77 * +----------------------------+-------------+-------------+-------------+-------------+
78 * Each cpu allocation will find the first (f2eec075) and use that buffer.
82 #define CPU_CONS_BUF_SIZE 256
83 #define CPU_BUF_FREE_HEX 0xf2eec075
85 #define KERN_CONSOLE_BUF_SIZE vm_map_round_page(CPU_CONS_BUF_SIZE *(MAX_CPU_SLOTS + 1), PAGE_SIZE - 1)
86 #define KERN_CONSOLE_RING_SIZE (KERN_CONSOLE_BUF_SIZE - (CPU_CONS_BUF_SIZE * MAX_CPU_SLOTS))
89 * A serial line running at 115200 bps can output ~11.5 characters per millisecond.
90 * Synchronous serial logging with preemption+interrupts disabled fundamentally prevents us
91 * from hitting expected scheduling deadlines, but we can at least tone it down a bit.
93 * TODO: IOLog should use asynchronous serial logging instead of the synchronous serial console. (26555148)
95 * Keep interrupt disabled periods shorter than 1ms
97 #define MAX_INT_DISABLED_FLUSH_SIZE 8
98 #define MAX_TOTAL_FLUSH_SIZE (MAX(2, MAX_CPU_SLOTS) * CPU_CONS_BUF_SIZE)
100 typedef struct console_buf
{
104 #define CPU_BUFFER_LEN (CPU_CONS_BUF_SIZE - 3 * (sizeof(char *)))
105 char buf
[CPU_BUFFER_LEN
];
108 extern int serial_getc(void);
109 extern void serial_putc(char);
111 static void _serial_putc(int, int, int);
113 SECURITY_READ_ONLY_EARLY(struct console_ops
) cons_ops
[] = {
115 .putc
= _serial_putc
, .getc
= _serial_getc
,
118 .putc
= vcputc
, .getc
= vcgetc
,
122 SECURITY_READ_ONLY_EARLY(uint32_t) nconsops
= (sizeof cons_ops
/ sizeof cons_ops
[0]);
124 uint32_t cons_ops_index
= VC_CONS_OPS
;
127 static bool console_suspended
= false;
130 console_ring_lock_init(void)
132 simple_lock_init(&console_ring
.read_lock
, 0);
133 simple_lock_init(&console_ring
.write_lock
, 0);
142 if (!OSCompareAndSwap(0, KERN_CONSOLE_RING_SIZE
, (UInt32
*)&console_ring
.len
))
145 assert(console_ring
.len
> 0);
147 ret
= kmem_alloc(kernel_map
, (vm_offset_t
*)&console_ring
.buffer
, KERN_CONSOLE_BUF_SIZE
, VM_KERN_MEMORY_OSFMK
);
148 if (ret
!= KERN_SUCCESS
) {
149 panic("console_ring_init() failed to allocate ring buffer, error %d\n", ret
);
152 /* setup memory for per cpu console buffers */
153 for (i
= 0; i
< MAX_CPU_SLOTS
; i
++) {
154 p
= (uint32_t *)((uintptr_t)console_ring
.buffer
+ console_ring
.len
+ (i
* sizeof(console_buf_t
)));
155 *p
= CPU_BUF_FREE_HEX
;
158 console_ring
.used
= 0;
159 console_ring
.read_ptr
= console_ring
.buffer
;
160 console_ring
.write_ptr
= console_ring
.buffer
;
161 console_ring_lock_init();
162 hw_lock_init(&cnputc_lock
);
166 console_cpu_alloc(__unused boolean_t boot_processor
)
173 assert(console_ring
.buffer
!= NULL
);
175 /* select the next slot from the per cpu buffers at end of console_ring.buffer */
176 for (i
= 0; i
< MAX_CPU_SLOTS
; i
++) {
177 p
= (uint32_t *)((uintptr_t)console_ring
.buffer
+ console_ring
.len
+ (i
* sizeof(console_buf_t
)));
178 if (OSCompareAndSwap(CPU_BUF_FREE_HEX
, 0, (UInt32
*)p
))
181 assert(i
< MAX_CPU_SLOTS
);
183 cbp
= (console_buf_t
*)(uintptr_t)p
;
184 if ((uintptr_t)cbp
>= (uintptr_t)console_ring
.buffer
+ KERN_CONSOLE_BUF_SIZE
) {
185 printf("console_cpu_alloc() failed to allocate cpu buffer\n");
189 cbp
->buf_base
= (char *)&cbp
->buf
;
190 cbp
->buf_ptr
= cbp
->buf_base
;
191 cbp
->buf_end
= cbp
->buf_base
+ CPU_BUFFER_LEN
;
196 console_cpu_free(void * buf
)
198 assert((uintptr_t)buf
> (uintptr_t)console_ring
.buffer
);
199 assert((uintptr_t)buf
< (uintptr_t)console_ring
.buffer
+ KERN_CONSOLE_BUF_SIZE
);
201 *(uint32_t *)buf
= CPU_BUF_FREE_HEX
;
205 console_ring_space(void)
207 return console_ring
.len
- console_ring
.used
;
211 console_ring_put(char ch
)
213 if (console_ring
.used
< console_ring
.len
) {
215 *console_ring
.write_ptr
++ = ch
;
216 if (console_ring
.write_ptr
- console_ring
.buffer
== console_ring
.len
)
217 console_ring
.write_ptr
= console_ring
.buffer
;
224 static inline boolean_t
225 cpu_buffer_put(console_buf_t
* cbp
, char ch
)
227 if (ch
!= '\0' && cbp
->buf_ptr
< cbp
->buf_end
) {
228 *(cbp
->buf_ptr
++) = ch
;
236 cpu_buffer_size(console_buf_t
* cbp
)
238 return (int)(cbp
->buf_ptr
- cbp
->buf_base
);
242 _cnputs(char * c
, int size
)
244 /* The console device output routines are assumed to be
248 uint32_t lock_timeout_ticks
= UINT32_MAX
;
250 uint32_t lock_timeout_ticks
= LockTimeOut
;
253 mp_disable_preemption();
254 if (!hw_lock_to(&cnputc_lock
, lock_timeout_ticks
)) {
255 /* If we timed out on the lock, and we're in the debugger,
256 * copy lock data for debugging and break the lock.
258 hw_lock_data_t _shadow_lock
;
259 memcpy(&_shadow_lock
, &cnputc_lock
, sizeof(cnputc_lock
));
261 /* Since hw_lock_to takes a pre-emption count...*/
262 mp_enable_preemption();
263 hw_lock_init(&cnputc_lock
);
264 hw_lock_lock(&cnputc_lock
);
266 panic("Lock acquire timeout in _cnputs() lock=%p, lock owner thread=0x%lx, current_thread: %p\n", &_shadow_lock
,
267 _shadow_lock
.lock_data
, current_thread());
272 cons_ops
[cons_ops_index
].putc(0, 0, *c
);
274 cons_ops
[cons_ops_index
].putc(0, 0, '\r');
278 hw_lock_unlock(&cnputc_lock
);
279 mp_enable_preemption();
283 cnputc_unbuffered(char c
)
293 /* Spin (with pre-emption enabled) waiting for console_ring_try_empty()
294 * to complete output. There is a small window here where we could
295 * end up with a stale value of console_output, but it's unlikely,
296 * and _cnputs(), which outputs to the console device, is internally
297 * synchronized. There's something of a conflict between the
298 * character-at-a-time (with pre-emption enabled) unbuffered
299 * output model here, and the buffered output from cnputc(),
300 * whose consumers include printf() ( which outputs a sequence
301 * with pre-emption disabled, and should be safe to call with
302 * interrupts off); we don't want to disable pre-emption indefinitely
303 * here, and spinlocks and mutexes are inappropriate.
305 while (console_output
!= 0)
309 * We disable interrupts to avoid issues caused by rendevous IPIs
310 * and an interruptible core holding the lock while an uninterruptible
311 * core wants it. Stackshot is the prime example of this.
313 state
= ml_set_interrupts_enabled(FALSE
);
315 ml_set_interrupts_enabled(state
);
319 console_ring_try_empty(void)
322 boolean_t handle_tlb_flushes
= (ml_get_interrupts_enabled() == FALSE
);
323 #endif /* __x86_64__ */
326 int total_chars_out
= 0;
327 int size_before_wrap
= 0;
331 if (handle_tlb_flushes
)
332 handle_pending_TLB_flushes();
333 #endif /* __x86_64__ */
336 * Try to get the read lock on the ring buffer to empty it.
337 * If this fails someone else is already emptying...
339 if (!simple_lock_try(&console_ring
.read_lock
)) {
341 * If multiple cores are spinning trying to empty the buffer,
342 * we may suffer lock starvation (get the read lock, but
343 * never the write lock, with other cores unable to get the
344 * read lock). As a result, insert a delay on failure, to
345 * let other cores have a turn.
351 boolean_t state
= ml_set_interrupts_enabled(FALSE
);
353 /* Indicate that we're in the process of writing a block of data to the console. */
354 (void)hw_atomic_add(&console_output
, 1);
356 simple_lock_try_lock_loop(&console_ring
.write_lock
);
358 /* try small chunk at a time, so we allow writes from other cpus into the buffer */
359 nchars_out
= MIN(console_ring
.used
, MAX_INT_DISABLED_FLUSH_SIZE
);
361 /* account for data to be read before wrap around */
362 size_before_wrap
= (int)((console_ring
.buffer
+ console_ring
.len
) - console_ring
.read_ptr
);
363 if (nchars_out
> size_before_wrap
)
364 nchars_out
= size_before_wrap
;
366 if (nchars_out
> 0) {
367 _cnputs(console_ring
.read_ptr
, nchars_out
);
368 console_ring
.read_ptr
=
369 console_ring
.buffer
+ ((console_ring
.read_ptr
- console_ring
.buffer
+ nchars_out
) % console_ring
.len
);
370 console_ring
.used
-= nchars_out
;
371 total_chars_out
+= nchars_out
;
374 simple_unlock(&console_ring
.write_lock
);
376 (void)hw_atomic_sub(&console_output
, 1);
378 simple_unlock(&console_ring
.read_lock
);
380 ml_set_interrupts_enabled(state
);
383 * In case we end up being the console drain thread
384 * for far too long, break out. Except in panic/suspend cases
385 * where we should clear out full buffer.
387 if (debug_mode
== 0 && !console_suspended
&& (total_chars_out
>= MAX_TOTAL_FLUSH_SIZE
))
390 } while (nchars_out
> 0);
397 console_suspended
= true;
398 console_ring_try_empty();
404 console_suspended
= false;
408 console_write(char * str
, int size
)
411 int chunk_size
= size
;
414 if (size
> console_ring
.len
)
415 chunk_size
= CPU_CONS_BUF_SIZE
;
418 boolean_t state
= ml_set_interrupts_enabled(FALSE
);
420 simple_lock_try_lock_loop(&console_ring
.write_lock
);
421 while (chunk_size
> console_ring_space()) {
422 simple_unlock(&console_ring
.write_lock
);
423 ml_set_interrupts_enabled(state
);
425 console_ring_try_empty();
427 state
= ml_set_interrupts_enabled(FALSE
);
428 simple_lock_try_lock_loop(&console_ring
.write_lock
);
431 for (i
= 0; i
< chunk_size
; i
++)
432 console_ring_put(str
[i
]);
436 simple_unlock(&console_ring
.write_lock
);
437 ml_set_interrupts_enabled(state
);
440 console_ring_try_empty();
447 cpu_data_t
* cpu_data_p
;
449 boolean_t needs_print
= TRUE
;
453 mp_disable_preemption();
454 cpu_data_p
= current_cpu_datap();
455 cbp
= (console_buf_t
*)cpu_data_p
->cpu_console_buf
;
456 if (console_suspended
|| cbp
== NULL
) {
457 mp_enable_preemption();
458 /* Put directly if console ring is not initialized or we're heading into suspend */
464 /* Is there a panic backtrace going on? */
465 if (cpu_data_p
->PAB_active
) {
466 /* If another processor was in the process of emptying the
467 * console ring buffer when it received the panic backtrace
468 * signal, that processor will be spinning in DebugXCall()
469 * waiting for the panicking processor to finish printing
470 * the backtrace. But panicking processor will never
471 * be able to obtain the ring buffer lock since it is
472 * owned by a processor that's spinning in DebugXCall().
473 * Blow away any locks that other processors may have on
474 * the console ring buffer so that the backtrace can
477 console_ring_lock_init();
479 #endif /* __x86_64__ */
481 state
= ml_set_interrupts_enabled(FALSE
);
485 * If the cpu buffer is full, we'll flush, then try
486 * another put. If it fails a second time... screw
489 if (needs_print
&& !cpu_buffer_put(cbp
, c
)) {
490 simple_lock_try_lock_loop(&console_ring
.write_lock
);
492 if (cpu_buffer_size(cbp
) > console_ring_space()) {
493 simple_unlock(&console_ring
.write_lock
);
494 ml_set_interrupts_enabled(state
);
495 mp_enable_preemption();
497 console_ring_try_empty();
501 for (cp
= cbp
->buf_base
; cp
< cbp
->buf_ptr
; cp
++)
502 console_ring_put(*cp
);
503 cbp
->buf_ptr
= cbp
->buf_base
;
504 simple_unlock(&console_ring
.write_lock
);
506 cpu_buffer_put(cbp
, c
);
512 ml_set_interrupts_enabled(state
);
513 mp_enable_preemption();
517 /* We printed a newline, time to flush the CPU buffer to the global buffer */
518 simple_lock_try_lock_loop(&console_ring
.write_lock
);
521 * Is there enough space in the shared ring buffer?
522 * Try to empty if not.
523 * Note, we want the entire local buffer to fit to
524 * avoid another cpu interjecting.
527 if (cpu_buffer_size(cbp
) > console_ring_space()) {
528 simple_unlock(&console_ring
.write_lock
);
529 ml_set_interrupts_enabled(state
);
530 mp_enable_preemption();
532 console_ring_try_empty();
537 for (cp
= cbp
->buf_base
; cp
< cbp
->buf_ptr
; cp
++)
538 console_ring_put(*cp
);
540 cbp
->buf_ptr
= cbp
->buf_base
;
541 simple_unlock(&console_ring
.write_lock
);
542 ml_set_interrupts_enabled(state
);
543 mp_enable_preemption();
545 console_ring_try_empty();
551 _serial_getc(__unused
int a
, __unused
int b
, boolean_t wait
, __unused boolean_t raw
)
556 } while (wait
&& c
< 0);
563 _serial_putc(__unused
int a
, __unused
int b
, int c
)
571 return cons_ops
[cons_ops_index
].getc(0, 0, TRUE
, FALSE
);
577 return cons_ops
[cons_ops_index
].getc(0, 0, FALSE
, FALSE
);
581 vcgetc(__unused
int l
, __unused
int u
, __unused boolean_t wait
, __unused boolean_t raw
)
585 if (0 == (*PE_poll_input
)(0, &c
))