hrev46518 adds 7 changesets to branch 'master' old head: 84ec24f2ff4aacf10ffc2a7f59ae7788c00f49f5 new head: c259766f94e7cfbe9318eda438d89f62a5099949 overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=c259766+%5E84ec24f ---------------------------------------------------------------------------- 7a1e706: safemode.h: Update coding style 9bdb5e0: kernel safemode: Add functions to get options early Add get_safemode_option_early() and get_safemode_boolean_early() to get safemode options before the kernel heap has been initialized. They use a simplified parser. 647b768: x86: Disable PAE, if 4 GB memory limit safemode is set fc7801b: boot loader: apply_boot_settings(): Replace string literal a3fe978: boot loader: Always show 4 GB memory limit safemode option On x86 we mainly want to disable PAE, which is now also used with less memory as long as NX support is available. Ideally we'd check this condition as well and only add the menu item, if the kernel would enable PAE. 5d3978d: KDL "mapping" command: Fix argument check It wasn't possible to actually specify the second argument (team ID). c259766: KDL "mapping" command: Allow specifying a thread ID ... instead of only a team ID. [ Ingo Weinhold <ingo_weinhold@xxxxxx> ] ---------------------------------------------------------------------------- 6 files changed, 265 insertions(+), 66 deletions(-) headers/private/kernel/safemode.h | 22 +- src/system/boot/loader/load_driver_settings.cpp | 4 +- src/system/boot/loader/menu.cpp | 8 +- .../kernel/arch/x86/arch_vm_translation_map.cpp | 12 +- src/system/kernel/debug/safemode_settings.cpp | 228 ++++++++++++++++--- src/system/kernel/vm/vm.cpp | 57 +++-- ############################################################################ Commit: 7a1e706df778d7cc0d5a10a20f8397660c274e2a URL: http://cgit.haiku-os.org/haiku/commit/?id=7a1e706 Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Tue Dec 10 16:07:20 2013 UTC safemode.h: Update coding style ---------------------------------------------------------------------------- diff --git a/headers/private/kernel/safemode.h b/headers/private/kernel/safemode.h index c61ba0d..308edfa 100644 --- a/headers/private/kernel/safemode.h +++ b/headers/private/kernel/safemode.h @@ -5,6 +5,7 @@ #ifndef _KERNEL_SAFEMODE_H #define _KERNEL_SAFEMODE_H + #include <driver_settings.h> #include <safemode_defs.h> @@ -14,12 +15,17 @@ extern "C" { #endif -status_t get_safemode_option(const char *parameter, char *buffer, size_t *_bufferSize); -bool get_safemode_boolean(const char *parameter, bool defaultValue); -status_t _user_get_safemode_option(const char *parameter, char *buffer, size_t *_bufferSize); + +status_t get_safemode_option(const char* parameter, char* buffer, + size_t* _bufferSize); +bool get_safemode_boolean(const char* parameter, bool defaultValue); +status_t _user_get_safemode_option(const char* parameter, char* buffer, + size_t* _bufferSize); + #ifdef __cplusplus } #endif + #endif /* _KERNEL_SAFEMODE_H */ ############################################################################ Commit: 9bdb5e0a928dcaa7d44f3111cb44e7a3a6d9bae2 URL: http://cgit.haiku-os.org/haiku/commit/?id=9bdb5e0 Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Tue Dec 10 18:05:47 2013 UTC kernel safemode: Add functions to get options early Add get_safemode_option_early() and get_safemode_boolean_early() to get safemode options before the kernel heap has been initialized. They use a simplified parser. ---------------------------------------------------------------------------- diff --git a/headers/private/kernel/safemode.h b/headers/private/kernel/safemode.h index 308edfa..bcf5751 100644 --- a/headers/private/kernel/safemode.h +++ b/headers/private/kernel/safemode.h @@ -11,6 +11,9 @@ #include <safemode_defs.h> +struct kernel_args; + + #ifdef __cplusplus extern "C" { #endif @@ -19,6 +22,13 @@ extern "C" { status_t get_safemode_option(const char* parameter, char* buffer, size_t* _bufferSize); bool get_safemode_boolean(const char* parameter, bool defaultValue); + +// before driver_settings_init() has been called (limited parsing support) +status_t get_safemode_option_early(kernel_args* args, const char* parameter, + char* buffer, size_t* _bufferSize); +bool get_safemode_boolean_early(kernel_args* args, const char* parameter, + bool defaultValue); + status_t _user_get_safemode_option(const char* parameter, char* buffer, size_t* _bufferSize); diff --git a/src/system/kernel/debug/safemode_settings.cpp b/src/system/kernel/debug/safemode_settings.cpp index 2cb9950..61334ae 100644 --- a/src/system/kernel/debug/safemode_settings.cpp +++ b/src/system/kernel/debug/safemode_settings.cpp @@ -4,59 +4,194 @@ */ +#include <safemode.h> + +#include <ctype.h> +#include <string.h> + +#include <algorithm> + #include <KernelExport.h> -#include <safemode.h> +#include <boot/kernel_args.h> #include <kernel.h> #include <syscalls.h> -#include <string.h> +#ifndef _BOOT_MODE -extern "C" status_t -get_safemode_option(const char* parameter, char* buffer, size_t* _bufferSize) + +static status_t +get_option_from_kernel_args(kernel_args* args, const char* settingsName, + const char* parameter, size_t parameterLength, char* buffer, + size_t* _bufferSize) { - status_t status = B_ENTRY_NOT_FOUND; + // find the settings in the kernel args + const char* settings = NULL; + for (driver_settings_file* file = args->driver_settings; + file != NULL; file = file->next) { + if (strcmp(settingsName, file->name) == 0) { + settings = file->buffer; + break; + } + } + + if (settings == NULL) + return B_ENTRY_NOT_FOUND; + + // Unfortunately we can't just use parse_driver_settings_string(), since + // we might not have a working heap yet. So we do very limited parsing + // ourselves. + const char* settingsEnd = settings + strlen(settings); + int32 parameterLevel = 0; + + while (*settings != '\0') { + // find end of line + const char* lineEnd = strchr(settings, '\n'); + const char* nextLine; + if (lineEnd != NULL) + nextLine = lineEnd + 1; + else + nextLine = lineEnd = settingsEnd; + + // ignore any trailing comments + lineEnd = std::find(settings, lineEnd, '#'); + + const char* nameStart = NULL; + const char* nameEnd = NULL; + const char* valueStart = NULL; + const char* valueEnd = NULL; + const char** elementEnd = NULL; + bool sawSeparator = true; + + for (; settings < lineEnd; settings++) { + switch (*settings) { + case '{': + parameterLevel++; + sawSeparator = true; + break; + + case '}': + parameterLevel--; + sawSeparator = true; + break; + + case ';': + // TODO: That's not correct. There should be another loop. + sawSeparator = true; + break; - void* handle = load_driver_settings(B_SAFEMODE_DRIVER_SETTINGS); - if (handle != NULL) { - status = B_NAME_NOT_FOUND; + default: + if (parameterLevel != 0) + break; - const char* value = get_driver_parameter(handle, parameter, NULL, NULL); - if (value != NULL) { - *_bufferSize = strlcpy(buffer, value, *_bufferSize); - status = B_OK; + if (isspace(*settings)) { + sawSeparator = true; + break; + } + + if (!sawSeparator) + break; + + sawSeparator = false; + + if (nameStart == NULL) { + nameStart = settings; + elementEnd = &nameEnd; + } else if (valueStart == NULL) { + valueStart = settings; + elementEnd = &valueEnd; + } + break; + } + + if (sawSeparator && elementEnd != NULL) { + *elementEnd = settings; + elementEnd = NULL; + } } - unload_driver_settings(handle); - } + if (elementEnd != NULL) + *elementEnd = settings; - if (status != B_OK) { - // Try kernel settings file as a fall back - handle = load_driver_settings("kernel"); - if (handle != NULL) { - const char* value = get_driver_parameter(handle, parameter, NULL, - NULL); - if (value != NULL) { - *_bufferSize = strlcpy(buffer, value, *_bufferSize); - status = B_OK; + if (nameStart != NULL && size_t(nameEnd - nameStart) == parameterLength + && strncmp(parameter, nameStart, parameterLength) == 0) { + if (valueStart == NULL) + return B_NAME_NOT_FOUND; + + size_t length = valueEnd - valueStart; + if (*_bufferSize > 0) { + size_t toCopy = std::min(length, *_bufferSize - 1); + memcpy(buffer, valueStart, toCopy); + buffer[toCopy] = '\0'; } - unload_driver_settings(handle); + *_bufferSize = length; + return B_OK; } + + settings = nextLine; } + return B_NAME_NOT_FOUND; +} + + +#endif // !_BOOT_MODE + + +static status_t +get_option(kernel_args* args, const char* settingsName, const char* parameter, + size_t parameterLength, char* buffer, size_t* _bufferSize) +{ +#ifndef _BOOT_MODE + if (args != NULL) { + return get_option_from_kernel_args(args, settingsName, parameter, + parameterLength, buffer, _bufferSize); + } +#endif + + void* handle = load_driver_settings(settingsName); + if (handle == NULL) + return B_ENTRY_NOT_FOUND; + + status_t status = B_NAME_NOT_FOUND; + + const char* value = get_driver_parameter(handle, parameter, NULL, NULL); + if (value != NULL) { + *_bufferSize = strlcpy(buffer, value, *_bufferSize); + status = B_OK; + } + + unload_driver_settings(handle); return status; } -extern "C" bool -get_safemode_boolean(const char* parameter, bool defaultValue) +static status_t +get_option(kernel_args* args, const char* parameter, char* buffer, + size_t* _bufferSize) +{ + size_t parameterLength = strlen(parameter); + status_t status = get_option(args, B_SAFEMODE_DRIVER_SETTINGS, parameter, + parameterLength, buffer, _bufferSize); + if (status != B_OK) { + // Try kernel settings file as a fall back + status = get_option(args, "kernel", parameter, parameterLength, buffer, + _bufferSize); + } + + return status; +} + + +static bool +get_boolean(kernel_args* args, const char* parameter, bool defaultValue) { char value[16]; size_t length = sizeof(value); - if (get_safemode_option(parameter, value, &length) != B_OK) + if (get_option(args, parameter, value, &length) != B_OK) return defaultValue; return !strcasecmp(value, "on") || !strcasecmp(value, "true") @@ -65,6 +200,45 @@ get_safemode_boolean(const char* parameter, bool defaultValue) } +// #pragma mark - + + +status_t +get_safemode_option(const char* parameter, char* buffer, size_t* _bufferSize) +{ + return get_option(NULL, parameter, buffer, _bufferSize); +} + + +bool +get_safemode_boolean(const char* parameter, bool defaultValue) +{ + return get_boolean(NULL, parameter, defaultValue); +} + + +#ifndef _BOOT_MODE + + +status_t +get_safemode_option_early(kernel_args* args, const char* parameter, + char* buffer, size_t* _bufferSize) +{ + return get_option(args, parameter, buffer, _bufferSize); +} + + +bool +get_safemode_boolean_early(kernel_args* args, const char* parameter, + bool defaultValue) +{ + return get_boolean(args, parameter, defaultValue); +} + + +#endif // _BOOT_MODE + + // #pragma mark - syscalls ############################################################################ Commit: 647b768f543c4d275390856edcc733327d7ae30c URL: http://cgit.haiku-os.org/haiku/commit/?id=647b768 Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Tue Dec 10 18:07:01 2013 UTC x86: Disable PAE, if 4 GB memory limit safemode is set ---------------------------------------------------------------------------- diff --git a/src/system/kernel/arch/x86/arch_vm_translation_map.cpp b/src/system/kernel/arch/x86/arch_vm_translation_map.cpp index c9ac7a4..728dbd8 100644 --- a/src/system/kernel/arch/x86/arch_vm_translation_map.cpp +++ b/src/system/kernel/arch/x86/arch_vm_translation_map.cpp @@ -11,6 +11,7 @@ #include <arch/vm_translation_map.h> #include <boot/kernel_args.h> +#include <safemode.h> #ifdef __x86_64__ # include "paging/64bit/X86PagingMethod64Bit.h" @@ -99,12 +100,17 @@ arch_vm_translation_map_init(kernel_args *args, } } - if (paeAvailable && paeNeeded) { + bool paeDisabled = get_safemode_boolean_early(args, + B_SAFEMODE_4_GB_MEMORY_LIMIT, false); + + if (paeAvailable && paeNeeded && !paeDisabled) { dprintf("using PAE paging\n"); gX86PagingMethod = new(&sPagingMethodBuffer) X86PagingMethodPAE; } else { - dprintf("using 32 bit paging (PAE not %s)\n", - paeNeeded ? "available" : "needed"); + dprintf("using 32 bit paging (PAE %s)\n", + paeNeeded + ? "not available" + : (paeDisabled ? "disabled" : "not needed")); gX86PagingMethod = new(&sPagingMethodBuffer) X86PagingMethod32Bit; } #else ############################################################################ Commit: fc7801bc6fb1df1acb384f1bf15cdc1638037e73 URL: http://cgit.haiku-os.org/haiku/commit/?id=fc7801b Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Tue Dec 10 18:08:07 2013 UTC boot loader: apply_boot_settings(): Replace string literal ---------------------------------------------------------------------------- diff --git a/src/system/boot/loader/load_driver_settings.cpp b/src/system/boot/loader/load_driver_settings.cpp index 65aca1d..5eabfd4 100644 --- a/src/system/boot/loader/load_driver_settings.cpp +++ b/src/system/boot/loader/load_driver_settings.cpp @@ -67,8 +67,8 @@ apply_boot_settings(void* kernelSettings, void* safemodeSettings) { #if B_HAIKU_PHYSICAL_BITS > 32 if ((kernelSettings != NULL - && get_driver_boolean_parameter(kernelSettings, "4gb_memory_limit", - false, false)) + && get_driver_boolean_parameter(kernelSettings, + B_SAFEMODE_4_GB_MEMORY_LIMIT, false, false)) || (safemodeSettings != NULL && get_driver_boolean_parameter(safemodeSettings, B_SAFEMODE_4_GB_MEMORY_LIMIT, false, false))) { ############################################################################ Commit: a3fe978f8ab957ea216b6d50982c7da2b70abea2 URL: http://cgit.haiku-os.org/haiku/commit/?id=a3fe978 Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Tue Dec 10 18:12:16 2013 UTC boot loader: Always show 4 GB memory limit safemode option On x86 we mainly want to disable PAE, which is now also used with less memory as long as NX support is available. Ideally we'd check this condition as well and only add the menu item, if the kernel would enable PAE. ---------------------------------------------------------------------------- diff --git a/src/system/boot/loader/menu.cpp b/src/system/boot/loader/menu.cpp index 400b8e4..8f35f19 100644 --- a/src/system/boot/loader/menu.cpp +++ b/src/system/boot/loader/menu.cpp @@ -1135,8 +1135,12 @@ add_safe_mode_menu() } } - // ... add the menu, if so - if (hasMemoryBeyond4GB) { + bool needs64BitPaging = true; + // TODO: Determine whether 64 bit paging (i.e. PAE for x86) is needed + // for other reasons (NX support). + + // ... add the menu item, if so + if (hasMemoryBeyond4GB || needs64BitPaging) { safeMenu->AddItem( item = new(nothrow) MenuItem("Ignore memory beyond 4 GiB")); item->SetData(B_SAFEMODE_4_GB_MEMORY_LIMIT); ############################################################################ Commit: 5d3978dbe7351942a45066d3f0b70ce8973144b4 URL: http://cgit.haiku-os.org/haiku/commit/?id=5d3978d Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Tue Dec 10 18:13:08 2013 UTC KDL "mapping" command: Fix argument check It wasn't possible to actually specify the second argument (team ID). ---------------------------------------------------------------------------- diff --git a/src/system/kernel/vm/vm.cpp b/src/system/kernel/vm/vm.cpp index 0d2dea1..f342e19 100644 --- a/src/system/kernel/vm/vm.cpp +++ b/src/system/kernel/vm/vm.cpp @@ -3432,7 +3432,7 @@ dump_mapping_info(int argc, char** argv) // We need at least one argument, the address. Optionally a team ID can be // specified. - if (argi >= argc || argi + 1 < argc) { + if (argi >= argc || argi + 2 < argc) { print_debugger_command_usage(argv[0]); return 0; } ############################################################################ Revision: hrev46518 Commit: c259766f94e7cfbe9318eda438d89f62a5099949 URL: http://cgit.haiku-os.org/haiku/commit/?id=c259766 Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Tue Dec 10 18:13:56 2013 UTC KDL "mapping" command: Allow specifying a thread ID ... instead of only a team ID. ---------------------------------------------------------------------------- diff --git a/src/system/kernel/vm/vm.cpp b/src/system/kernel/vm/vm.cpp index f342e19..d4a01cc 100644 --- a/src/system/kernel/vm/vm.cpp +++ b/src/system/kernel/vm/vm.cpp @@ -3430,7 +3430,7 @@ dump_mapping_info(int argc, char** argv) } } - // We need at least one argument, the address. Optionally a team ID can be + // We need at least one argument, the address. Optionally a thread ID can be // specified. if (argi >= argc || argi + 2 < argc) { print_debugger_command_usage(argv[0]); @@ -3441,11 +3441,19 @@ dump_mapping_info(int argc, char** argv) if (!evaluate_debug_expression(argv[argi++], &addressValue, false)) return 0; - uint64 teamID = B_CURRENT_TEAM; - bool teamSpecified = argi < argc; - if (teamSpecified) { - if (!evaluate_debug_expression(argv[argi++], &teamID, false)) + Team* team = NULL; + if (argi < argc) { + uint64 threadID = -1; + if (!evaluate_debug_expression(argv[argi++], &threadID, false)) return 0; + + Thread* thread = Thread::GetDebug(threadID); + if (thread == NULL) { + kprintf("Invalid thread/team ID \"%s\"\n", argv[argi - 1]); + return 0; + } + + team = thread->team; } if (reverseLookup) { @@ -3488,20 +3496,9 @@ dump_mapping_info(int argc, char** argv) VMAddressSpace* fAddressSpace; } callback; - if (teamSpecified) { + if (team != NULL) { // team specified -- get its address space - VMAddressSpace* addressSpace; - if (teamID == B_CURRENT_TEAM) { - Thread* thread = debug_get_debugged_thread(); - if (thread == NULL || thread->team == NULL) { - kprintf("Failed to get team!\n"); - return 0; - } - - addressSpace = thread->team->address_space; - } else - addressSpace = VMAddressSpace::DebugGet(teamID); - + VMAddressSpace* addressSpace = team->address_space; if (addressSpace == NULL) { kprintf("Failed to get address space!\n"); return 0; @@ -3527,7 +3524,9 @@ dump_mapping_info(int argc, char** argv) VMAddressSpace* addressSpace; if (IS_KERNEL_ADDRESS(virtualAddress)) { addressSpace = VMAddressSpace::Kernel(); - } else if (!teamSpecified || teamID == B_CURRENT_TEAM) { + } else if (team != NULL) { + addressSpace = team->address_space; + } else { Thread* thread = debug_get_debugged_thread(); if (thread == NULL || thread->team == NULL) { kprintf("Failed to get team!\n"); @@ -3535,8 +3534,7 @@ dump_mapping_info(int argc, char** argv) } addressSpace = thread->team->address_space; - } else - addressSpace = VMAddressSpace::DebugGet(teamID); + } if (addressSpace == NULL) { kprintf("Failed to get address space!\n"); @@ -4078,16 +4076,17 @@ vm_init(kernel_args* args) add_debugger_command_etc("mapping", &dump_mapping_info, "Print address mapping information", - "[ \"-r\" | \"-p\" ] <address> [ <team ID> ]\n" + "[ \"-r\" | \"-p\" ] <address> [ <thread ID> ]\n" "Prints low-level page mapping information for a given address. If\n" "neither \"-r\" nor \"-p\" are specified, <address> is a virtual\n" "address that is looked up in the translation map of the current\n" - "team, respectively the team specified by ID <team ID>. If \"-r\" is\n" - "specified, <address> is a physical address that is searched in the\n" - "translation map of all teams, respectively the team specified by ID\n" - " <team ID>. If \"-p\" is specified, <address> is the address of a\n" - "vm_page structure. The behavior is equivalent to specifying \"-r\"\n" - "with the physical address of that page.\n", + "team, respectively the team specified by thread ID <thread ID>. If\n" + "\"-r\" is specified, <address> is a physical address that is\n" + "searched in the translation map of all teams, respectively the team\n" + "specified by thread ID <thread ID>. If \"-p\" is specified,\n" + "<address> is the address of a vm_page structure. The behavior is\n" + "equivalent to specifying \"-r\" with the physical address of that\n" + "page.\n", 0); TRACE(("vm_init: exit\n"));