summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorRichard Braun <rbraun@sceen.net>2014-01-08 20:19:25 +0100
committerRichard Braun <rbraun@sceen.net>2014-01-08 20:19:38 +0100
commit19c29e22f64dfd66c07e88f9e8ffc9b2a1beab65 (patch)
tree794c1d84aee5436751a35c3f6337d18286af2326 /arch
parenta07fad83320e5c1f8c1efe8a716a74731a852e99 (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.c13
-rw-r--r--arch/x86/machine/boot.c25
-rw-r--r--arch/x86/machine/boot.h11
-rw-r--r--arch/x86/machine/boot_asm.S26
-rw-r--r--arch/x86/machine/pmap.c5
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;