From 28a2172c3f19a34e31ba20085148e5428544823a Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Thu, 11 Mar 2010 17:46:36 +0000 Subject: [PATCH] kernel: * The kernel syslog ring buffer is no longer emptied by the syslog sender thread. Instead we only drop the oldest data from the buffer when we're writing to it and there's not enough free space in it. Advantages: We drop old data rather than the most recent data when the buffer is full. The "syslog" KDL command has more data available now. So the odds are that kernel syslog messages not written to disk yet are at least still in the kernel buffer. * Changed dprintf_no_syslog() semantics: Now it writes to the syslog, but doesn't notify the syslog sender thread. boot loader: * Added the ring_buffer implementation and a dummy user_memcpy(). * bios_x86: Moved the syslog stuff from serial.{cpp,h} to debug.{cpp.h}. * Moved the debug options from the "Select safe mode options" menu to a new "Select debug options" menu. * Added option "Enable debug syslog" to the new menu (ATM available on x86 only). It allocates a 1 MB in-memory buffer for the syslog for this session in such a way that it can be accessed by the boot loader after a reset. * Added item "Display syslog from previous session" to the new menu, doing what its name suggests. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35816 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/kernel/boot/kernel_args.h | 1 + src/system/boot/loader/Jamfile | 21 +-- src/system/boot/loader/menu.cpp | 105 ++++++++++++-- src/system/boot/loader/vm.cpp | 17 +++ src/system/boot/platform/bios_ia32/Jamfile | 6 +- src/system/boot/platform/bios_ia32/debug.c | 57 -------- src/system/boot/platform/bios_ia32/debug.cpp | 134 ++++++++++++++++++ src/system/boot/platform/bios_ia32/debug.h | 24 ++++ src/system/boot/platform/bios_ia32/serial.cpp | 24 ---- src/system/boot/platform/bios_ia32/serial.h | 1 + src/system/boot/platform/bios_ia32/start.c | 29 ++-- src/system/kernel/debug/debug.cpp | 111 +++++++++------ 12 files changed, 372 insertions(+), 158 deletions(-) create mode 100644 src/system/boot/loader/vm.cpp delete mode 100644 src/system/boot/platform/bios_ia32/debug.c create mode 100644 src/system/boot/platform/bios_ia32/debug.cpp create mode 100644 src/system/boot/platform/bios_ia32/debug.h diff --git a/headers/private/kernel/boot/kernel_args.h b/headers/private/kernel/boot/kernel_args.h index 4e80a99dbb..742a27fee1 100644 --- a/headers/private/kernel/boot/kernel_args.h +++ b/headers/private/kernel/boot/kernel_args.h @@ -78,6 +78,7 @@ typedef struct kernel_args { void *debug_output; uint32 debug_size; + bool keep_debug_output_buffer; platform_kernel_args platform_args; arch_kernel_args arch_args; diff --git a/src/system/boot/loader/Jamfile b/src/system/boot/loader/Jamfile index 10b505f01a..9ca8495f46 100644 --- a/src/system/boot/loader/Jamfile +++ b/src/system/boot/loader/Jamfile @@ -50,17 +50,19 @@ UsePrivateHeaders shared storage ; } KernelStaticLibrary boot_loader : - main.cpp - vfs.cpp - RootFileSystem.cpp - partitions.cpp - heap.cpp - stdio.cpp elf.cpp - menu.cpp - loader.cpp + heap.cpp kernel_args.cpp load_driver_settings.cpp + loader.cpp + main.cpp + menu.cpp + pager.cpp + partitions.cpp + RootFileSystem.cpp + stdio.cpp + vfs.cpp + vm.cpp # libroot driver_settings.c @@ -69,6 +71,7 @@ KernelStaticLibrary boot_loader : kernel_cpp.cpp KMessage.cpp list.cpp + ring_buffer.cpp safemode_settings.cpp : -fno-pic @@ -89,7 +92,7 @@ KernelStaticLibrary boot_partitions : ; # Tell Jam where to find the utility sources -SEARCH on [ FGristFiles kernel_cpp.cpp list.cpp ] +SEARCH on [ FGristFiles kernel_cpp.cpp list.cpp ring_buffer.cpp ] = [ FDirName $(HAIKU_TOP) src system kernel util ] ; SEARCH on [ FGristFiles KMessage.cpp ] diff --git a/src/system/boot/loader/menu.cpp b/src/system/boot/loader/menu.cpp index 6f8d45b630..c26a4001a5 100644 --- a/src/system/boot/loader/menu.cpp +++ b/src/system/boot/loader/menu.cpp @@ -5,23 +5,26 @@ #include "menu.h" -#include "loader.h" -#include "RootFileSystem.h" -#include "load_driver_settings.h" + +#include #include #include -#include #include #include #include #include #include #include +#include +#include -#include +#include "load_driver_settings.h" +#include "loader.h" +#include "pager.h" +#include "RootFileSystem.h" #define TRACE_MENU @@ -375,6 +378,48 @@ user_menu_boot_volume(Menu *menu, MenuItem *item) } +static bool +debug_menu_display_syslog(Menu *menu, MenuItem *item) +{ + ring_buffer* buffer = (ring_buffer*)gKernelArgs.debug_output; + if (buffer == NULL) + return true; + + struct TextSource : PagerTextSource { + TextSource(ring_buffer* buffer) + : + fBuffer(buffer) + { + } + + virtual size_t BytesAvailable() const + { + return ring_buffer_readable(fBuffer); + } + + virtual size_t Read(size_t offset, void* buffer, size_t size) const + { + return ring_buffer_peek(fBuffer, offset, buffer, size); + } + + private: + ring_buffer* fBuffer; + }; + + pager(TextSource(buffer)); + + return true; +} + + +static bool +debug_menu_toggle_debug_syslog(Menu *menu, MenuItem *item) +{ + gKernelArgs.keep_debug_output_buffer = item->IsMarked(); + return true; +} + + static Menu * add_boot_volume_menu(Directory *bootVolume) { @@ -459,34 +504,66 @@ add_safe_mode_menu() platform_add_menus(safeMenu); + safeMenu->AddSeparatorItem(); + safeMenu->AddItem(item = new(nothrow) MenuItem("Return to main menu")); + + return safeMenu; +} + + +static Menu * +add_debug_menu() +{ + Menu *menu = new(nothrow) Menu(SAFE_MODE_MENU, "Debug Options"); + MenuItem *item; + #if DEBUG_SPINLOCK_LATENCIES item = new(std::nothrow) MenuItem("Disable latency checks"); if (item != NULL) { item->SetType(MENU_ITEM_MARKABLE); item->SetData(B_SAFEMODE_DISABLE_LATENCY_CHECK); item->SetHelpText("Disables latency check panics."); - safeMenu->AddItem(item); + menu->AddItem(item); } #endif - safeMenu->AddItem(item + menu->AddItem(item = new(nothrow) MenuItem("Enable serial debug output")); item->SetData("serial_debug_output"); item->SetType(MENU_ITEM_MARKABLE); item->SetHelpText("Turns on forwarding the syslog output to the serial " "interface."); - safeMenu->AddItem(item + menu->AddItem(item = new(nothrow) MenuItem("Enable on screen debug output")); item->SetData("debug_screen"); item->SetType(MENU_ITEM_MARKABLE); item->SetHelpText("Displays debug output on screen while the system " "is booting, instead of the normal boot logo."); - safeMenu->AddSeparatorItem(); - safeMenu->AddItem(item = new(nothrow) MenuItem("Return to main menu")); + menu->AddItem(item = new(nothrow) MenuItem("Enable debug syslog")); + item->SetType(MENU_ITEM_MARKABLE); + item->SetMarked(gKernelArgs.keep_debug_output_buffer); + item->SetTarget(&debug_menu_toggle_debug_syslog); + item->SetHelpText("Enables a special in-memory syslog buffer for this " + "session that the boot loader will be able to access after rebooting."); - return safeMenu; + ring_buffer* syslogBuffer = (ring_buffer*)gKernelArgs.debug_output; + if (syslogBuffer != NULL && ring_buffer_readable(syslogBuffer) > 0) { + menu->AddSeparatorItem(); + + menu->AddItem(item + = new(nothrow) MenuItem("Display syslog from previous session")); + item->SetTarget(&debug_menu_display_syslog); + item->SetType(MENU_ITEM_NO_CHOICE); + item->SetHelpText( + "Displays the syslog from the previous Haiku session."); + } + + menu->AddSeparatorItem(); + menu->AddItem(item = new(nothrow) MenuItem("Return to main menu")); + + return menu; } @@ -527,6 +604,7 @@ user_menu(Directory **_bootVolume) { Menu *menu = new(nothrow) Menu(MAIN_MENU); Menu *safeModeMenu = NULL; + Menu *debugMenu = NULL; MenuItem *item; TRACE(("user_menu: enter\n")); @@ -539,6 +617,10 @@ user_menu(Directory **_bootVolume) menu->AddItem(item = new(nothrow) MenuItem("Select safe mode options", safeModeMenu = add_safe_mode_menu())); + // add debug menu + menu->AddItem(item = new(nothrow) MenuItem("Select debug options", + debugMenu = add_debug_menu())); + // Add platform dependent menus platform_add_menus(menu); @@ -561,6 +643,7 @@ user_menu(Directory **_bootVolume) *_bootVolume = (Directory *)item->Data(); apply_safe_mode_options(safeModeMenu); + apply_safe_mode_options(debugMenu); delete menu; TRACE(("user_menu: leave\n")); diff --git a/src/system/boot/loader/vm.cpp b/src/system/boot/loader/vm.cpp new file mode 100644 index 0000000000..4f8411fabe --- /dev/null +++ b/src/system/boot/loader/vm.cpp @@ -0,0 +1,17 @@ +/* + * Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + + +#include + +#include + + +status_t +user_memcpy(void* to, const void* from, size_t size) +{ + memcpy(to, from, size); + return B_OK; +} diff --git a/src/system/boot/platform/bios_ia32/Jamfile b/src/system/boot/platform/bios_ia32/Jamfile index ef03efd27f..501a663d49 100644 --- a/src/system/boot/platform/bios_ia32/Jamfile +++ b/src/system/boot/platform/bios_ia32/Jamfile @@ -17,7 +17,7 @@ UsePrivateHeaders [ FDirName storage ] ; SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src add-ons accelerants common ] ; -local genericPlatformSources = +local genericPlatformSources = text_menu.cpp video_blit.cpp video_splash.cpp @@ -27,7 +27,7 @@ local genericPlatformSources = KernelMergeObject boot_platform_bios_ia32.o : shell.S start.c - debug.c + debug.cpp bios.S console.cpp serial.cpp @@ -44,7 +44,7 @@ KernelMergeObject boot_platform_bios_ia32.o : video.cpp apm.cpp hpet.cpp - + $(genericPlatformSources) # VESA/DDC EDID diff --git a/src/system/boot/platform/bios_ia32/debug.c b/src/system/boot/platform/bios_ia32/debug.c deleted file mode 100644 index 23094c0009..0000000000 --- a/src/system/boot/platform/bios_ia32/debug.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de. - * Distributed under the terms of the MIT License. - */ - - -#include "serial.h" -#include "keyboard.h" - -#include -#include -#include - - -/*! This works only after console_init() was called. -*/ -void -panic(const char *format, ...) -{ - va_list list; - - platform_switch_to_text_mode(); - - puts("*** PANIC ***"); - - va_start(list, format); - vprintf(format, list); - va_end(list); - - puts("\nPress key to reboot."); - - clear_key_buffer(); - wait_for_key(); - platform_exit(); -} - - -void -dprintf(const char *format, ...) -{ - char buffer[512]; - va_list list; - int length; - - va_start(list, format); - length = vsnprintf(buffer, sizeof(buffer), format, list); - va_end(list); - - if (length >= (int)sizeof(buffer)) - length = sizeof(buffer) - 1; - - serial_puts(buffer, length); - - if (platform_boot_options() & BOOT_OPTION_DEBUG_OUTPUT) - fprintf(stderr, "%s", buffer); -} - diff --git a/src/system/boot/platform/bios_ia32/debug.cpp b/src/system/boot/platform/bios_ia32/debug.cpp new file mode 100644 index 0000000000..9966553404 --- /dev/null +++ b/src/system/boot/platform/bios_ia32/debug.cpp @@ -0,0 +1,134 @@ +/* + * Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ + + +#include "debug.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include "keyboard.h" +#include "mmu.h" +#include "serial.h" + + +static const char* const kDebugSyslogSignature = "Haiku syslog"; + +static char sBuffer[16384]; +static uint32 sBufferPosition; + +static ring_buffer* sDebugSyslogBuffer = NULL; + + +/*! This works only after console_init() was called. +*/ +void +panic(const char *format, ...) +{ + va_list list; + + platform_switch_to_text_mode(); + + puts("*** PANIC ***"); + + va_start(list, format); + vprintf(format, list); + va_end(list); + + puts("\nPress key to reboot."); + + clear_key_buffer(); + wait_for_key(); + platform_exit(); +} + + +void +dprintf(const char *format, ...) +{ + char buffer[512]; + va_list list; + int length; + + va_start(list, format); + length = vsnprintf(buffer, sizeof(buffer), format, list); + va_end(list); + + if (length >= (int)sizeof(buffer)) + length = sizeof(buffer) - 1; + + if (sBufferPosition + length < sizeof(sBuffer)) { + memcpy(sBuffer + sBufferPosition, buffer, length); + sBufferPosition += length; + } + + serial_puts(buffer, length); + + if (platform_boot_options() & BOOT_OPTION_DEBUG_OUTPUT) + fprintf(stderr, "%s", buffer); +} + + +// #pragma mark - + + +void +debug_init_post_mmu(void) +{ + // allocate 1 MB memory at 16 MB + addr_t base = 16 * 1024 * 1024; + size_t size = 1024 * 1024; + if (!mmu_allocate_physical(base, size)) + return; + + void* buffer = (void*)mmu_map_physical_memory(base, size, + kDefaultPageFlags); + if (buffer == NULL) + return; + + // check whether there's a previous syslog we can recover + size_t signatureLength = strlen(kDebugSyslogSignature); + bool recover = memcmp(buffer, kDebugSyslogSignature, signatureLength) == 0; + + // clear the signature + memset(buffer, 0, signatureLength); + + size -= signatureLength; + buffer = (uint8*)buffer + ROUNDUP(signatureLength, sizeof(void*)); + + sDebugSyslogBuffer = create_ring_buffer_etc(buffer, size, + recover ? RING_BUFFER_INIT_FROM_BUFFER : 0); + + gKernelArgs.debug_output = sDebugSyslogBuffer; + gKernelArgs.debug_size = sDebugSyslogBuffer->size; +} + + +void +debug_cleanup(void) +{ + if (gKernelArgs.keep_debug_output_buffer && sDebugSyslogBuffer != NULL) { + // copy the output gathered so far into the ring buffer + ring_buffer_clear(sDebugSyslogBuffer); + ring_buffer_write(sDebugSyslogBuffer, (uint8*)sBuffer, sBufferPosition); + + // set the buffer signature, so we'll accept it as valid after reboot + size_t signatureLength = strlen(kDebugSyslogSignature); + memcpy((void*)ROUNDDOWN((addr_t)sDebugSyslogBuffer, B_PAGE_SIZE), + kDebugSyslogSignature, signatureLength); + } else { + gKernelArgs.debug_output = kernel_args_malloc(sBufferPosition); + if (gKernelArgs.debug_output != NULL) { + memcpy(gKernelArgs.debug_output, sBuffer, sBufferPosition); + gKernelArgs.debug_size = sBufferPosition; + } + } +} diff --git a/src/system/boot/platform/bios_ia32/debug.h b/src/system/boot/platform/bios_ia32/debug.h new file mode 100644 index 0000000000..08ec6a471b --- /dev/null +++ b/src/system/boot/platform/bios_ia32/debug.h @@ -0,0 +1,24 @@ +/* + * Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef DEBUG_H +#define DEBUG_H + + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +void debug_init_post_mmu(void); +void debug_cleanup(void); + +#ifdef __cplusplus +} +#endif + + +#endif // DEBUG_H diff --git a/src/system/boot/platform/bios_ia32/serial.cpp b/src/system/boot/platform/bios_ia32/serial.cpp index c460091801..440a6d20ea 100644 --- a/src/system/boot/platform/bios_ia32/serial.cpp +++ b/src/system/boot/platform/bios_ia32/serial.cpp @@ -34,10 +34,6 @@ static const uint32 kSerialBaudRate = 115200; static int32 sSerialEnabled = 0; static uint16 sSerialBasePort = 0x3f8; -static char sBuffer[16384]; -static uint32 sBufferPosition; - - static void serial_putc(char c) { @@ -55,11 +51,6 @@ serial_puts(const char* string, size_t size) if (sSerialEnabled <= 0) return; - if (sBufferPosition + size < sizeof(sBuffer)) { - memcpy(sBuffer + sBufferPosition, string, size); - sBufferPosition += size; - } - while (size-- != 0) { char c = string[0]; @@ -92,20 +83,6 @@ serial_enable(void) } -extern "C" void -serial_cleanup(void) -{ - if (sSerialEnabled <= 0) - return; - - gKernelArgs.debug_output = kernel_args_malloc(sBufferPosition); - if (gKernelArgs.debug_output != NULL) { - memcpy(gKernelArgs.debug_output, sBuffer, sBufferPosition); - gKernelArgs.debug_size = sBufferPosition; - } -} - - extern "C" void serial_init(void) { @@ -133,4 +110,3 @@ serial_init(void) serial_enable(); #endif } - diff --git a/src/system/boot/platform/bios_ia32/serial.h b/src/system/boot/platform/bios_ia32/serial.h index 5db0789eda..03c564794e 100644 --- a/src/system/boot/platform/bios_ia32/serial.h +++ b/src/system/boot/platform/bios_ia32/serial.h @@ -14,6 +14,7 @@ extern "C" { #endif extern void serial_init(void); +extern void serial_init_post_mmu(void); extern void serial_cleanup(void); extern void serial_puts(const char *string, size_t size); diff --git a/src/system/boot/platform/bios_ia32/start.c b/src/system/boot/platform/bios_ia32/start.c index 3d9535abe0..997fb18b1a 100644 --- a/src/system/boot/platform/bios_ia32/start.c +++ b/src/system/boot/platform/bios_ia32/start.c @@ -4,24 +4,26 @@ */ -#include "serial.h" -#include "console.h" -#include "apm.h" -#include "cpu.h" -#include "mmu.h" -#include "smp.h" -#include "acpi.h" -#include "keyboard.h" -#include "bios.h" -#include "multiboot.h" +#include #include + +#include #include #include #include -#include -#include +#include "acpi.h" +#include "apm.h" +#include "bios.h" +#include "console.h" +#include "cpu.h" +#include "debug.h" +#include "keyboard.h" +#include "mmu.h" +#include "multiboot.h" +#include "serial.h" +#include "smp.h" #define HEAP_SIZE (128 * 1024) @@ -79,7 +81,7 @@ platform_start_kernel(void) = gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size; smp_init_other_cpus(); - serial_cleanup(); + debug_cleanup(); mmu_init_for_kernel(); smp_boot_other_cpus(); @@ -128,6 +130,7 @@ _start(void) console_init(); cpu_init(); mmu_init(); + debug_init_post_mmu(); parse_multiboot_commandline(&args); // reading the keyboard doesn't seem to work in graphics mode diff --git a/src/system/kernel/debug/debug.cpp b/src/system/kernel/debug/debug.cpp index ea9c462882..17ee4daa42 100644 --- a/src/system/kernel/debug/debug.cpp +++ b/src/system/kernel/debug/debug.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de. * Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. * @@ -91,6 +91,7 @@ static int32 sDebuggerOnCPU = -1; static sem_id sSyslogNotify = -1; static struct syslog_message* sSyslogMessage; static struct ring_buffer* sSyslogBuffer; +static size_t sSyslogBufferOffset = 0; static bool sSyslogDropped = false; static const char* sCurrentKernelDebuggerMessagePrefix; @@ -106,7 +107,7 @@ static DebugOutputFilter* sDebugOutputFilter = NULL; DefaultDebugOutputFilter gDefaultDebugOutputFilter; static mutex sOutputLock = MUTEX_INITIALIZER("debug output"); -static void flush_pending_repeats(bool syslogOutput); +static void flush_pending_repeats(bool notifySyslog); static void check_pending_repeats(void* data, int iter); static int64 sMessageRepeatFirstTime = 0; @@ -180,7 +181,7 @@ void DefaultDebugOutputFilter::Print(const char* format, va_list args) { vsnprintf(sInterruptOutputBuffer, OUTPUT_BUFFER_SIZE, format, args); - flush_pending_repeats(sInDebugger == 0); + flush_pending_repeats(false); PrintString(sInterruptOutputBuffer); } @@ -1065,12 +1066,14 @@ syslog_sender(void* data) cpu_status state = disable_interrupts(); acquire_spinlock(&sSpinlock); - length = ring_buffer_readable(sSyslogBuffer); + length = ring_buffer_readable(sSyslogBuffer) + - sSyslogBufferOffset; if (length > (int32)SYSLOG_MAX_MESSAGE_LENGTH) length = SYSLOG_MAX_MESSAGE_LENGTH; - length = ring_buffer_read(sSyslogBuffer, + length = ring_buffer_peek(sSyslogBuffer, sSyslogBufferOffset, (uint8*)sSyslogMessage->message, length); + sSyslogBufferOffset += length; if (sSyslogDropped) { // Add drop marker - since parts had to be dropped, it's // guaranteed that we have enough space in the buffer now. @@ -1111,29 +1114,33 @@ syslog_sender(void* data) static void -syslog_write(const char* text, int32 length) +syslog_write(const char* text, int32 length, bool notify) { - bool trunc = false; - if (sSyslogBuffer == NULL) return; - if ((int32)ring_buffer_writable(sSyslogBuffer) < length) { - // truncate data - length = ring_buffer_writable(sSyslogBuffer); + if (length > sSyslogBuffer->size) { + text = ""; + length = 6; + } - if (length > 8) { - trunc = true; - length -= 8; - } else + int32 writable = ring_buffer_writable(sSyslogBuffer); + if (writable < length) { + // drop old data + size_t toDrop = length - writable; + ring_buffer_flush(sSyslogBuffer, toDrop); + + if (toDrop > sSyslogBufferOffset) { + sSyslogBufferOffset = 0; sSyslogDropped = true; + } else + sSyslogBufferOffset -= toDrop; } ring_buffer_write(sSyslogBuffer, (uint8*)text, length); - if (trunc) - ring_buffer_write(sSyslogBuffer, (uint8*)"", 7); - release_sem_etc(sSyslogNotify, 1, B_DO_NOT_RESCHEDULE); + if (notify) + release_sem_etc(sSyslogNotify, 1, B_DO_NOT_RESCHEDULE); } @@ -1163,7 +1170,7 @@ syslog_init_post_threads(void) static status_t -syslog_init(struct kernel_args* args) +syslog_init_post_vm(struct kernel_args* args) { status_t status; int32 length = 0; @@ -1177,7 +1184,7 @@ syslog_init(struct kernel_args* args) goto err1; } - { + if (sSyslogBuffer == NULL) { size_t bufferSize = DEFAULT_SYSLOG_BUFFER_SIZE; void* handle = load_driver_settings("kernel"); if (handle != NULL) { @@ -1195,10 +1202,17 @@ syslog_init(struct kernel_args* args) } sSyslogBuffer = create_ring_buffer(bufferSize); - } - if (sSyslogBuffer == NULL) { - status = B_NO_MEMORY; - goto err2; + + if (sSyslogBuffer == NULL) { + status = B_NO_MEMORY; + goto err2; + } + } else { + // create an area for the debug syslog buffer + void* base = (void*)ROUNDDOWN((addr_t)args->debug_output, B_PAGE_SIZE); + size_t size = ROUNDUP(args->debug_size, B_PAGE_SIZE); + create_area("syslog debug", &base, B_EXACT_ADDRESS, size, + B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); } // initialize syslog message @@ -1209,14 +1223,14 @@ syslog_init(struct kernel_args* args) //strcpy(sSyslogMessage->ident, "KERNEL"); if (args->debug_output != NULL) - syslog_write((const char*)args->debug_output, args->debug_size); + syslog_write((const char*)args->debug_output, args->debug_size, false); char revisionBuffer[64]; length = snprintf(revisionBuffer, sizeof(revisionBuffer), "Welcome to syslog debug output!\nHaiku revision: %lu\n", get_haiku_revision()); syslog_write(revisionBuffer, - std::min(length, (ssize_t)sizeof(revisionBuffer) - 1)); + std::min(length, (ssize_t)sizeof(revisionBuffer) - 1), false); add_debugger_command_etc("syslog", &cmd_dump_syslog, "Dumps the syslog buffer.", @@ -1236,6 +1250,19 @@ err1: } +static status_t +syslog_init(struct kernel_args* args) +{ + if (!args->keep_debug_output_buffer) + return B_OK; + + sSyslogBuffer = create_ring_buffer_etc(args->debug_output, args->debug_size, + RING_BUFFER_INIT_FROM_BUFFER); + + return B_OK; +} + + static void debug_memcpy_trampoline(void* _parameters) { @@ -1273,7 +1300,7 @@ call_modules_hook(bool enter) //! Must be called with the sSpinlock held. static void -debug_output(const char* string, int32 length, bool syslogOutput) +debug_output(const char* string, int32 length, bool notifySyslog) { if (length >= OUTPUT_BUFFER_SIZE) length = OUTPUT_BUFFER_SIZE - 1; @@ -1285,12 +1312,12 @@ debug_output(const char* string, int32 length, bool syslogOutput) if (sMessageRepeatFirstTime == 0) sMessageRepeatFirstTime = sMessageRepeatLastTime; } else { - flush_pending_repeats(syslogOutput); + flush_pending_repeats(notifySyslog); if (sSerialDebugEnabled) arch_debug_serial_puts(string); - if (sSyslogOutputEnabled && syslogOutput) - syslog_write(string, length); + if (sSyslogOutputEnabled) + syslog_write(string, length, notifySyslog); if (sBlueScreenEnabled || sDebugScreenEnabled) blue_screen_puts(string); if (sSerialDebugEnabled) { @@ -1308,7 +1335,7 @@ debug_output(const char* string, int32 length, bool syslogOutput) //! Must be called with the sSpinlock held. static void -flush_pending_repeats(bool syslogOutput) +flush_pending_repeats(bool notifySyslog) { if (sMessageRepeatCount <= 0) return; @@ -1321,8 +1348,8 @@ flush_pending_repeats(bool syslogOutput) if (sSerialDebugEnabled) arch_debug_serial_puts(temp); - if (sSyslogOutputEnabled && syslogOutput) - syslog_write(temp, length); + if (sSyslogOutputEnabled) + syslog_write(temp, length, notifySyslog); if (sBlueScreenEnabled || sDebugScreenEnabled) blue_screen_puts(temp); if (sSerialDebugEnabled) { @@ -1337,8 +1364,8 @@ flush_pending_repeats(bool syslogOutput) if (sSerialDebugEnabled) arch_debug_serial_puts(sLastOutputBuffer); - if (sSyslogOutputEnabled && syslogOutput) - syslog_write(sLastOutputBuffer, length); + if (sSyslogOutputEnabled) + syslog_write(sLastOutputBuffer, length, notifySyslog); if (sBlueScreenEnabled || sDebugScreenEnabled) blue_screen_puts(sLastOutputBuffer); if (sSerialDebugEnabled) { @@ -1374,7 +1401,7 @@ check_pending_repeats(void* /*data*/, int /*iteration*/) static void -dprintf_args(const char* format, va_list args, bool syslogOutput) +dprintf_args(const char* format, va_list args, bool notifySyslog) { if (are_interrupts_enabled()) { MutexLocker locker(sOutputLock); @@ -1384,7 +1411,7 @@ dprintf_args(const char* format, va_list args, bool syslogOutput) length = std::min(length, (int32)OUTPUT_BUFFER_SIZE - 1); InterruptsSpinLocker _(sSpinlock); - debug_output(sOutputBuffer, length, syslogOutput); + debug_output(sOutputBuffer, length, notifySyslog); } else { InterruptsSpinLocker _(sSpinlock); @@ -1392,7 +1419,7 @@ dprintf_args(const char* format, va_list args, bool syslogOutput) format, args); length = std::min(length, (int32)OUTPUT_BUFFER_SIZE - 1); - debug_output(sInterruptOutputBuffer, length, syslogOutput); + debug_output(sInterruptOutputBuffer, length, notifySyslog); } } @@ -1425,7 +1452,7 @@ void debug_puts(const char* string, int32 length) { InterruptsSpinLocker _(sSpinlock); - debug_output(string, length, sSyslogOutputEnabled); + debug_output(string, length, true); } @@ -1441,6 +1468,8 @@ debug_init(kernel_args* args) { new(&gDefaultDebugOutputFilter) DefaultDebugOutputFilter; + syslog_init(args); + debug_paranoia_init(); return arch_debug_console_init(args); } @@ -1484,7 +1513,7 @@ debug_init_post_vm(kernel_args* args) if (sDebugScreenEnabled) blue_screen_enter(true); - syslog_init(args); + syslog_init_post_vm(args); return arch_debug_init(args); } @@ -1785,7 +1814,7 @@ dprintf(const char* format, ...) return; va_start(args, format); - dprintf_args(format, args, sSyslogOutputEnabled); + dprintf_args(format, args, true); va_end(args); }