diff options
author | Richard Braun <rbraun@sceen.net> | 2014-01-08 20:19:25 +0100 |
---|---|---|
committer | Richard Braun <rbraun@sceen.net> | 2014-01-08 20:19:38 +0100 |
commit | 19c29e22f64dfd66c07e88f9e8ffc9b2a1beab65 (patch) | |
tree | 794c1d84aee5436751a35c3f6337d18286af2326 /arch | |
parent | a07fad83320e5c1f8c1efe8a716a74731a852e99 (diff) |
x86/boot: improve early error reporting
Move the error strings to the boot data section. In addition, add some
assembly code to report that a processor doesn't support long mode.
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/machine/biosmem.c | 13 | ||||
-rw-r--r-- | arch/x86/machine/boot.c | 25 | ||||
-rw-r--r-- | arch/x86/machine/boot.h | 11 | ||||
-rw-r--r-- | arch/x86/machine/boot_asm.S | 26 | ||||
-rw-r--r-- | arch/x86/machine/pmap.c | 5 |
5 files changed, 61 insertions, 19 deletions
diff --git a/arch/x86/machine/biosmem.c b/arch/x86/machine/biosmem.c index d999454..245181f 100644 --- a/arch/x86/machine/biosmem.c +++ b/arch/x86/machine/biosmem.c @@ -81,6 +81,13 @@ static uint32_t biosmem_heap_start __bootdata; static uint32_t biosmem_heap_free __bootdata; static uint32_t biosmem_heap_end __bootdata; +static char biosmem_panic_setup_msg[] __bootdata + = "biosmem: unable to set up the early memory allocator"; +static char biosmem_panic_inval_msg[] __bootdata + = "biosmem: attempt to allocate 0 page"; +static char biosmem_panic_nomem_msg[] __bootdata + = "biosmem: unable to allocate memory"; + static void __boot biosmem_map_build(const struct multiboot_raw_info *mbi) { @@ -243,7 +250,7 @@ biosmem_setup_allocator(struct multiboot_raw_info *mbi) max_heap_end = vm_page_trunc(max_heap_end); if (max_heap_start >= max_heap_end) - boot_panic("biosmem: unable to find memory for the boot allocator"); + boot_panic(biosmem_panic_setup_msg); biosmem_heap_start = max_heap_start; biosmem_heap_free = max_heap_start; @@ -309,14 +316,14 @@ biosmem_bootalloc(unsigned int nr_pages) char *ptr; if (nr_pages == 0) - boot_panic("biosmem: attempt to allocate 0 pages"); + boot_panic(biosmem_panic_inval_msg); free = biosmem_heap_free; page = free; free += PAGE_SIZE * nr_pages; if ((free <= biosmem_heap_start) || (free > biosmem_heap_end)) - boot_panic("biosmem: unable to allocate memory"); + boot_panic(biosmem_panic_nomem_msg); biosmem_heap_free = free; diff --git a/arch/x86/machine/boot.c b/arch/x86/machine/boot.c index 7daf5cc..02a4050 100644 --- a/arch/x86/machine/boot.c +++ b/arch/x86/machine/boot.c @@ -67,13 +67,6 @@ #include <vm/vm_page.h> #include <vm/vm_setup.h> -/* - * Macros used by the very early panic function. - */ -#define BOOT_CGAMEM ((uint16_t *)0xb8000) -#define BOOT_CGACHARS (80 * 25) -#define BOOT_CGACOLOR 0x7 - char boot_stacks[MAX_CPUS][BOOT_STACK_SIZE] __aligned(DATA_ALIGN) __initdata; unsigned int boot_ap_id __bootdata; @@ -81,6 +74,8 @@ unsigned int boot_ap_id __bootdata; pmap_pte_t boot_pml4[PMAP_L3_PTES_PER_PTP] __aligned(PAGE_SIZE) __bootdata; pmap_pte_t boot_pdpt[PMAP_L2_PTES_PER_PTP] __aligned(PAGE_SIZE) __bootdata; pmap_pte_t boot_pdir[4 * PMAP_L1_PTES_PER_PTP] __aligned(PAGE_SIZE) __bootdata; +char boot_panic_long_mode_msg[] __bootdata + = "boot: processor doesn't support long mode"; #endif /* __LP64__ */ /* @@ -89,21 +84,27 @@ pmap_pte_t boot_pdir[4 * PMAP_L1_PTES_PER_PTP] __aligned(PAGE_SIZE) __bootdata; static struct multiboot_raw_info boot_raw_mbi __bootdata; static struct multiboot_info boot_mbi __initdata; +static char boot_panic_intro_msg[] __bootdata = "panic: "; +static char boot_panic_loader_msg[] __bootdata + = "boot: not started by a multiboot compliant boot loader"; +static char boot_panic_meminfo_msg[] __bootdata + = "boot: missing basic memory information"; + void __boot boot_panic(const char *msg) { uint16_t *ptr, *end; const char *s; - ptr = BOOT_CGAMEM; + ptr = (uint16_t *)BOOT_CGAMEM; end = ptr + BOOT_CGACHARS; - s = (void *)BOOT_VTOP((unsigned long)"panic: "); + s = boot_panic_intro_msg; while ((ptr < end) && (*s != '\0')) *ptr++ = (BOOT_CGACOLOR << 8) | *s++; - s = BOOT_VTOP(msg); + s = msg; while ((ptr < end) && (*s != '\0')) *ptr++ = (BOOT_CGACOLOR << 8) | *s++; @@ -120,10 +121,10 @@ pmap_pte_t * __boot boot_setup_paging(const struct multiboot_raw_info *mbi, unsigned long eax) { if (eax != MULTIBOOT_LOADER_MAGIC) - boot_panic("not started by a multiboot compliant boot loader"); + boot_panic(boot_panic_loader_msg); if (!(mbi->flags & MULTIBOOT_LOADER_MEMORY)) - boot_panic("missing basic memory information"); + boot_panic(boot_panic_meminfo_msg); /* * Save the multiboot data passed by the boot loader, initialize the diff --git a/arch/x86/machine/boot.h b/arch/x86/machine/boot.h index 5b85c14..c0a5c94 100644 --- a/arch/x86/machine/boot.h +++ b/arch/x86/machine/boot.h @@ -22,6 +22,13 @@ #include <machine/param.h> /* + * Macros used by the very early panic functions. + */ +#define BOOT_CGAMEM 0xb8000 +#define BOOT_CGACHARS (80 * 25) +#define BOOT_CGACOLOR 0x7 + +/* * The kernel is physically loaded at BOOT_OFFSET by the boot loader. It * is divided in two parts: the .boot section which uses physical addresses * and the main kernel code and data at KERNEL_OFFSET. @@ -86,8 +93,8 @@ void boot_mp_trampoline(void); /* * Print the given message and halt the system immediately. * - * This function allows early initialization code to print something helpful - * before printk is available. + * The given string must be accessible before paging is enabled, which can + * easily be done by declaring it as boot data. */ void __noreturn boot_panic(const char *s); diff --git a/arch/x86/machine/boot_asm.S b/arch/x86/machine/boot_asm.S index c5f8f7b..da2b8f1 100644 --- a/arch/x86/machine/boot_asm.S +++ b/arch/x86/machine/boot_asm.S @@ -134,8 +134,32 @@ ASM_ENTRY(boot_check_long_mode) ASM_END(boot_check_long_mode) ASM_ENTRY(boot_no_long_mode) + movl $boot_panic_long_mode_msg, %esi + movl $BOOT_CGAMEM, %edi + movl $(BOOT_CGAMEM + (BOOT_CGACHARS * 2)), %edx + movw $(BOOT_CGACOLOR << 8), %ax + +1: + movb (%esi), %al + testb %al, %al + jz 1f + movw %ax, (%edi) + incl %esi + add $2, %edi + cmpl %edx, %edi + jae 2f + jmp 1b + +1: + cmpl %edx, %edi + jae 2f + movw $((BOOT_CGACOLOR << 8) + ' ), (%edi) + add $2, %edi + jmp 1b + +2: hlt - jmp boot_no_long_mode + jmp 2b ASM_END(boot_no_long_mode) ASM_ENTRY(boot_setup_long_mode) diff --git a/arch/x86/machine/pmap.c b/arch/x86/machine/pmap.c index 6464068..bf05376 100644 --- a/arch/x86/machine/pmap.c +++ b/arch/x86/machine/pmap.c @@ -119,6 +119,9 @@ struct pmap *kernel_pmap __read_mostly = &kernel_pmap_store; static unsigned long pmap_boot_heap __initdata; static unsigned long pmap_boot_heap_end __initdata; +static char pmap_panic_inval_msg[] __bootdata + = "pmap: invalid physical address"; + #ifdef X86_PAE /* * Alignment required on page directory pointer tables. @@ -213,7 +216,7 @@ pmap_boot_enter(pmap_pte_t *root_ptp, unsigned long va, phys_addr_t pa) pmap_pte_t *pt, *ptp, *pte; if (pa != (pa & PMAP_PA_MASK)) - boot_panic("pmap: invalid physical address"); + boot_panic(pmap_panic_inval_msg); pt_levels = (void *)BOOT_VTOP((unsigned long)pmap_pt_levels); pt = root_ptp; |