Author: bonefish Date: 2011-06-11 02:08:42 +0200 (Sat, 11 Jun 2011) New Revision: 42092 Changeset: https://dev.haiku-os.org/changeset/42092 Added: haiku/trunk/src/system/boot/platform/bios_ia32/bios.cpp haiku/trunk/src/system/boot/platform/bios_ia32/bios_asm.S haiku/trunk/src/system/boot/platform/bios_ia32/interrupts.cpp haiku/trunk/src/system/boot/platform/bios_ia32/interrupts.h haiku/trunk/src/system/boot/platform/bios_ia32/interrupts_asm.S Removed: haiku/trunk/src/system/boot/platform/bios_ia32/bios.S Modified: haiku/trunk/src/system/boot/platform/bios_ia32/Jamfile haiku/trunk/src/system/boot/platform/bios_ia32/debug.cpp haiku/trunk/src/system/boot/platform/bios_ia32/debug.h haiku/trunk/src/system/boot/platform/bios_ia32/mmu.cpp haiku/trunk/src/system/boot/platform/bios_ia32/shell.S haiku/trunk/src/system/boot/platform/bios_ia32/start.cpp haiku/trunk/src/system/boot/platform/pxe_ia32/Jamfile Log: * The boot loader does now set up an IDT that allows it to catch processor exceptions (page faults and the like). The handler dumps possibly interesting information (registers, a (numerical) stack trace) to the serial output, and, if possible, also to the screen. That should help debugging boot loader crashes. * For the IDT the boot loader sets up for the kernel the descriptors are set up the same way, so until the kernel initializes the IDT itself (arch_init()) the facility is still in place and can thus catch very early kernel boot crashes. Unfortunately the on-screen output doesn't seem to work anymore at that point, so the output only goes to the serial port... * ... and to the debug syslog -- dprintf() does now append it there after debug_cleanup() has been called. Seems to work fine in qemu, but when I tested it on real hardware the debug syslog was gone. Modified: haiku/trunk/src/system/boot/platform/bios_ia32/Jamfile =================================================================== --- haiku/trunk/src/system/boot/platform/bios_ia32/Jamfile 2011-06-10 22:31:33 UTC (rev 42091) +++ haiku/trunk/src/system/boot/platform/bios_ia32/Jamfile 2011-06-11 00:08:42 UTC (rev 42092) @@ -21,7 +21,8 @@ shell.S start.cpp debug.cpp - bios.S + bios.cpp + bios_asm.S console.cpp serial.cpp devices.cpp @@ -37,6 +38,8 @@ video.cpp apm.cpp hpet.cpp + interrupts.cpp + interrupts_asm.S # VESA/DDC EDID decode_edid.c Added: haiku/trunk/src/system/boot/platform/bios_ia32/bios.cpp =================================================================== --- haiku/trunk/src/system/boot/platform/bios_ia32/bios.cpp (rev 0) +++ haiku/trunk/src/system/boot/platform/bios_ia32/bios.cpp 2011-06-11 00:08:42 UTC (rev 42092) @@ -0,0 +1,22 @@ +/* + * Copyright 2011, Ingo Weinhold, ingo_weinhold@xxxxxxx + * Distributed under the terms of the MIT License. + */ + + +#include "bios.h" + +#include "interrupts.h" + + +extern "C" void call_bios_internal(uint8 num, struct bios_regs* regs); + + +void +call_bios(uint8 num, struct bios_regs* regs) +{ + restore_bios_idt(); + call_bios_internal(num, regs); + set_debug_idt(); + +} Copied: haiku/trunk/src/system/boot/platform/bios_ia32/bios_asm.S (from rev 42078, haiku/trunk/src/system/boot/platform/bios_ia32/bios.S) =================================================================== --- haiku/trunk/src/system/boot/platform/bios_ia32/bios_asm.S (rev 0) +++ haiku/trunk/src/system/boot/platform/bios_ia32/bios_asm.S 2011-06-11 00:08:42 UTC (rev 42092) @@ -0,0 +1,295 @@ +/* + * Copyright 2004-2010, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx + * Distributed under the terms of the MIT License. + */ + + +/*! This file contains code to call BIOS functions out of a protected + mode environment. It doesn't use the virtual86 mode - it switches + to real mode, make the BIOS call, and switch back to protected + mode again. It's meant to be used in a single-threaded boot loader, + not in a multi-tasking operating system. + It relies on the real mode segment descriptors found in shell.S. +*/ + + +#define FUNCTION(x) .globl x ; x ## : + +#define REAL_MODE_STACK 0x9000 + // the location of the stack in real mode + +#define SAVED_ESP 0x10000 +#define SAVED_CR3 0x10004 +#define SAVED_EAX 0x10008 +#define SAVED_ES 0x1000c +#define SAVED_FLAGS 0x10010 +#define SAVED_EBP 0x10014 + // we're overwriting the start of our boot loader to hold some + // temporary values - the first 1024 bytes of it are used at + // startup only, and we avoid some linking issues this way + + +.text +.code32 + + +/*! This function brings you back to protected mode after you've + switched to it using switch_to_real_mode(). + Should restore the whole environment to what it looked like + before. Clobbers %eax. +*/ +FUNCTION(switch_to_protected_mode) + cli // turn off interrupts + + .code16 + movl %cr0, %eax // set the PE bit (0) to switch to protected mode + orb $0x1, %al + movl %eax, %cr0 + + .code32 + .byte 0x66 // jump to the protected mode segment + ljmp $0x8, $_protected_code_segment +_protected_code_segment: + movw $0x10, %ax // setup data and stack selectors + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + movw %ax, %gs + movw %ax, %ss + + // turn on paging again + movl SAVED_CR3, %eax // restore the saved page directory + orl %eax, %eax // is there a paging directory at all? + jz _no_paging; + + movl %eax, %cr3 + + movl %cr0, %eax // set the PG bit (31) to enable paging + orl $0x80000000, %eax + movl %eax, %cr0 + +_no_paging: + // save the return address so that we can pick it up again later + movl (%esp), %eax + movl %eax, REAL_MODE_STACK + + // setup protected stack frame again + movl SAVED_ESP, %eax + movl %eax, %esp + movl SAVED_EBP, %ebp + + // copy the return address to the current stack + movl REAL_MODE_STACK, %eax + movl %eax, (%esp) + + ret + +//-------------------------------------------------------------- + + +/*! Switches from protected mode back to real mode. + It will disable paging and set the real mode segment selectors to 0x1000, + except for the stack selector, which will be 0x0 (the stack is at 0x9000 + which is where the BFS boot loader puts it as well). + Clobbers %eax. +*/ +FUNCTION(switch_to_real_mode) + // save the %esp register + movl %esp, %eax + movl %eax, SAVED_ESP + + movl %ebp, SAVED_EBP + + // put the return address on the real mode stack + movl (%esp), %eax + movl %eax, REAL_MODE_STACK + + // disable paging + movl %cr3, %eax // save the page directory address + movl %eax, SAVED_CR3 + + movl %cr0, %eax + andl $0x7fffffff, %eax // clear PG bit (31) + movl %eax, %cr0 + + xor %eax, %eax // clear page directory to flush TLBs + movl %eax, %cr3 + + // setup real mode stack + movl $REAL_MODE_STACK, %eax + movl %eax, %esp + movl %eax, %ebp + + // setup selectors to point to our 16 bit segments + movw $0x20, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + movw %ax, %gs + movw $0x28, %ax + movw %ax, %ss + + ljmp $0x18, $(_almost_real_code_segment - 0x10000) + +_almost_real_code_segment: + movl %cr0, %eax // switch to real mode + andb $0xfe, %al // clear PE bit (0) + movl %eax, %cr0 + + .byte 0x66 + ljmp $0x1000, $(_real_code_segment - 0x10000) + +_real_code_segment: + .code16 + movw $0x1000, %ax // setup data & stack segments + movw %ax, %ds // data in segment 0x1000, + movw %ax, %es + movw %ax, %fs + movw %ax, %gs + + xor %ax, %ax // stack in segment 0x0 + movw %ax, %ss + + sti // turn on interrupts again + ret + + .code32 + +//-------------------------------------------------------------- + + +/*! void call_bios_internal(uint8 num, struct bios_regs *regs) + Does a BIOS call by triggering a software interrupt in real + mode. +*/ +FUNCTION(call_bios_internal) + pushal + pushfl + + // make sure the correct IDT is in place + lidt idt_descriptor + + // get the interrupt vector and patch the instruction at the target address + movl 40(%esp), %eax + mov %al, int_number + + // Fills registers from the passed in structure + // Since switch_to_real_mode() clobbers %eax, we have to handle + // it specially here (by temporarily storing it to an arbitrary + // memory location, SAVED_EAX) + movl 44(%esp), %ebp + + movl (%ebp), %eax + movl %eax, SAVED_EAX + movl 4(%ebp), %ebx + movl 8(%ebp), %ecx + movl 12(%ebp), %edx + movl 16(%ebp), %esi + movl 20(%ebp), %edi + movw 24(%ebp), %ax + movw %ax, SAVED_ES + + call switch_to_real_mode + + .code16 + + // restore %eax and %es from saved location + movl (SAVED_EAX - 0x10000), %eax + movw (SAVED_ES - 0x10000), %es + + // call the interrupt (will be dynamically changed above) + .byte 0xcd +int_number: + .byte 0 + + // we're interested in the flags state as well + pushf + + // save %eax from the call + movl %eax, (SAVED_EAX - 0x10000) + + // save flags from the call + pop %ax + movw %ax, (SAVED_FLAGS - 0x10000) + + // back to protected mode + call switch_to_protected_mode + .code32 + + // store the register state into the structure that has been passed in + movl 44(%esp), %eax + + movl %ebx, 4(%eax) + movl %ecx, 8(%eax) + movl %edx, 12(%eax) + movl %esi, 16(%eax) + movl %edi, 20(%eax) + movl SAVED_EAX, %ecx // special handling for %eax and flags + movl %ecx, (%eax) + movw SAVED_FLAGS, %cx + movw %cx, 26(%eax) + + popfl + popal + + ret + +//-------------------------------------------------------------- + + +/*! uint32 boot_key_in_keyboard_buffer() + Search keyboard buffer for the keycodes for space in the first run, and, + if not found - for the escape key at the last two positions of this buffer +*/ +FUNCTION(boot_key_in_keyboard_buffer) + pushal + pushfl + + // make sure the correct IDT is in place + lidt idt_descriptor + + call switch_to_real_mode + .code16 + + cld + push %ds + xorl %eax, %eax + mov %ax, %ds + mov $0x41E, %si // BIOS kbd buffer +search_cycle1: + lodsw + cmp $0x3920, %ax // test space key + jz to_ret + cmp $0x440, %si + jnz search_cycle1 + + addw 0x41C, %si + movw -0x42(%si), %ax + cmp $0x011B, %ax // test ESC key + jz to_ret + movw -0x44(%si), %ax + cmp $0x011B, %ax // test ESC key +to_ret: + pop %ds + + // save %eax + movl %eax, (SAVED_EAX - 0x10000) + + call switch_to_protected_mode + .code32 + + popfl + popal + + // restore %eax + movl SAVED_EAX, %eax + + ret + +//-------------------------------------------------------------- + + +.globl idt_descriptor +idt_descriptor: + .short 0x7ff // IDT at 0x0, default real mode location + .long 0x0 Modified: haiku/trunk/src/system/boot/platform/bios_ia32/debug.cpp =================================================================== --- haiku/trunk/src/system/boot/platform/bios_ia32/debug.cpp 2011-06-10 22:31:33 UTC (rev 42091) +++ haiku/trunk/src/system/boot/platform/bios_ia32/debug.cpp 2011-06-11 00:08:42 UTC (rev 42092) @@ -6,7 +6,6 @@ #include "debug.h" -#include <stdarg.h> #include <string.h> #include <boot/platform.h> @@ -26,8 +25,35 @@ static uint32 sBufferPosition; static ring_buffer* sDebugSyslogBuffer = NULL; +static bool sPostCleanup = false; +static void +dprintf_args(const char *format, va_list args) +{ + char buffer[512]; + int length = vsnprintf(buffer, sizeof(buffer), format, args); + + if (length >= (int)sizeof(buffer)) + length = sizeof(buffer) - 1; + + if (sPostCleanup && sDebugSyslogBuffer != NULL) { + ring_buffer_write(sDebugSyslogBuffer, (const uint8*)buffer, length); + } else 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 - + + /*! This works only after console_init() was called. */ void @@ -54,26 +80,29 @@ void dprintf(const char *format, ...) { - char buffer[512]; - va_list list; - int length; + va_list args; - va_start(list, format); - length = vsnprintf(buffer, sizeof(buffer), format, list); - va_end(list); + va_start(args, format); + dprintf_args(format, args); + va_end(args); +} - if (length >= (int)sizeof(buffer)) - length = sizeof(buffer) - 1; - if (sBufferPosition + length < sizeof(sBuffer)) { - memcpy(sBuffer + sBufferPosition, buffer, length); - sBufferPosition += length; - } +void +kprintf(const char *format, ...) +{ + va_list args; - serial_puts(buffer, length); + va_start(args, format); - if (platform_boot_options() & BOOT_OPTION_DEBUG_OUTPUT) - fprintf(stderr, "%s", buffer); + // print to console, if available + if (stdout != NULL) + vfprintf(stdout, format, args); + + // always print to serial line + dprintf_args(format, args); + + va_end(args); } @@ -120,7 +149,8 @@ if (gKernelArgs.keep_debug_output_buffer) { // copy the output gathered so far into the ring buffer ring_buffer_clear(sDebugSyslogBuffer); - ring_buffer_write(sDebugSyslogBuffer, (uint8*)sBuffer, sBufferPosition); + ring_buffer_write(sDebugSyslogBuffer, (uint8*)sBuffer, + sBufferPosition); memcpy(buffer, kDebugSyslogSignature, signatureLength); } else { @@ -137,4 +167,6 @@ gKernelArgs.debug_size = sBufferPosition; } } + + sPostCleanup = true; } Modified: haiku/trunk/src/system/boot/platform/bios_ia32/debug.h =================================================================== --- haiku/trunk/src/system/boot/platform/bios_ia32/debug.h 2011-06-10 22:31:33 UTC (rev 42091) +++ haiku/trunk/src/system/boot/platform/bios_ia32/debug.h 2011-06-11 00:08:42 UTC (rev 42092) @@ -6,6 +6,8 @@ #define DEBUG_H +#include <stdarg.h> + #include <SupportDefs.h> Added: haiku/trunk/src/system/boot/platform/bios_ia32/interrupts.cpp =================================================================== --- haiku/trunk/src/system/boot/platform/bios_ia32/interrupts.cpp (rev 0) +++ haiku/trunk/src/system/boot/platform/bios_ia32/interrupts.cpp 2011-06-11 00:08:42 UTC (rev 42092) @@ -0,0 +1,249 @@ +/* + * Copyright 2011, Ingo Weinhold, ingo_weinhold@xxxxxxx + * Distributed under the terms of the MIT License. + */ + + +#include "interrupts.h" + +#include <stdio.h> +#include <string.h> + +#include <algorithm> + +#include <KernelExport.h> + +#include <boot/platform.h> +#include <boot/platform/generic/text_console.h> + +#include <arch_cpu.h> +#include <descriptors.h> + +#include "debug.h" +#include "keyboard.h" + + +//#define TRACE_INTERRUPTS +#ifdef TRACE_INTERRUPTS +# define TRACE(x...) dprintf(x) +#else +# define TRACE(x...) ; +#endif + + +// interrupt function prototypes +#define INTERRUPT_FUNCTION(vector) \ + extern "C" void interrupt_function##vector(); +INTERRUPT_FUNCTIONS() +#undef INTERRUPT_FUNCTION + +#define INTERRUPT_FUNCTION(vector) \ + extern "C" void exception_interrupt_function##vector(); +INTERRUPT_FUNCTIONS() +#undef INTERRUPT_FUNCTION + + +static const char *kInterruptNames[DEBUG_IDT_SLOT_COUNT] = { + /* 0 */ "Divide Error Exception", + /* 1 */ "Debug Exception", + /* 2 */ "NMI Interrupt", + /* 3 */ "Breakpoint Exception", + /* 4 */ "Overflow Exception", + /* 5 */ "BOUND Range Exceeded Exception", + /* 6 */ "Invalid Opcode Exception", + /* 7 */ "Device Not Available Exception", + /* 8 */ "Double Fault Exception", + /* 9 */ "Coprocessor Segment Overrun", + /* 10 */ "Invalid TSS Exception", + /* 11 */ "Segment Not Present", + /* 12 */ "Stack Fault Exception", + /* 13 */ "General Protection Exception", + /* 14 */ "Page-Fault Exception", + /* 15 */ "-", + /* 16 */ "x87 FPU Floating-Point Error", + /* 17 */ "Alignment Check Exception", + /* 18 */ "Machine-Check Exception", + /* 19 */ "SIMD Floating-Point Exception", +}; + + +struct interrupt_frame { + uint32 vector; + uint32 edi; + uint32 esi; + uint32 ebp; + uint32 esp; + uint32 ebx; + uint32 edx; + uint32 ecx; + uint32 eax; + uint32 error_code; + uint32 eip; + uint32 cs; + uint32 eflags; +}; + +struct interrupt_descriptor { + uint32 a; + uint32 b; +}; + + +static interrupt_descriptor sDebugIDT[DEBUG_IDT_SLOT_COUNT]; + +static gdt_idt_descr sBIOSIDTDescriptor; +static gdt_idt_descr sDebugIDTDescriptor = { sizeof(sDebugIDT) - 1, sDebugIDT }; + + +static void +set_interrupt_gate(int n, void (*function)()) +{ + if (n >= DEBUG_IDT_SLOT_COUNT) + return; + + sDebugIDT[n].a = (KERNEL_CODE_SEG << 16) | (0x0000ffff & (addr_t)function); + sDebugIDT[n].b = (0xffff0000 & (addr_t)function) | 0x8e00; +} + + +static void +set_idt(const gdt_idt_descr& idtDescriptor) +{ + asm("lidt %0;" : : "m" (idtDescriptor)); +} + + +extern "C" void +handle_exception_exception() +{ + while (true); +} + + +extern "C" void +handle_exception(interrupt_frame frame) +{ + // Before doing anything else, set the interrupt gates so that + // handle_exception_exception() is called. This way we may avoid + // triple-faulting, if e.g. the stack is messed up and the user has at + // least the already printed output. + #define INTERRUPT_FUNCTION(vector) \ + set_interrupt_gate(vector, &exception_interrupt_function##vector); + INTERRUPT_FUNCTIONS() + #undef INTERRUPT_FUNCTION + + // If the console is already/still initialized, clear the screen and prepare + // for output. + if (stdout != NULL) { + console_set_color(RED, BLACK); + console_clear_screen(); + console_set_cursor(0, 0); + console_hide_cursor(); + } + + // print exception name + if (frame.vector < DEBUG_IDT_SLOT_COUNT) + kprintf("%s", kInterruptNames[frame.vector]); + else + kprintf("Unknown exception %" B_PRIu32, frame.vector); + + // additional info for page fault + if (frame.vector == 14) { + uint32 cr2; + asm("movl %%cr2, %0" : "=r"(cr2)); + kprintf(": %s fault at address: %#" B_PRIx32, + (frame.error_code & 0x2) != 0 ? "write" : "read", cr2); + } + + kprintf("\n"); + + // print greeting and registers + kprintf("Welcome to Boot Loader Death Land!\n"); + kprintf("\n"); + + #define REG(name) " " #name " %-#10" B_PRIx32 + + kprintf(REG(eax) " " REG(ebx) " " REG(ecx) " " REG(edx) "\n", + frame.eax, frame.ebx, frame.ecx, frame.edx); + kprintf(REG(esi) " " REG(edi) " " REG(ebp) " " REG(esp) "\n", + frame.esi, frame.edi, frame.ebp, frame.esp); + kprintf(REG(eip) REG(eflags) "\n", frame.eip, frame.eflags); + + #undef REG + + // print stack trace (max 10 frames) + kprintf("\n frame return address\n"); + + struct x86_stack_frame { + x86_stack_frame* next; + void* return_address; + }; + + x86_stack_frame* stackFrame = (x86_stack_frame*)frame.ebp; + void* instructionPointer = (void*)frame.eip; + + for (int32 i = 0; i < 10 && stackFrame != NULL; i++) { + kprintf(" %p %p\n", stackFrame, instructionPointer); + + instructionPointer = stackFrame->return_address; + stackFrame = stackFrame->next; + } + + if (stdout != NULL) { + kprintf("\nPress a key to reboot.\n"); + clear_key_buffer(); + wait_for_key(); + platform_exit(); + } + + while (true); +} + + +void +interrupts_init() +{ + // get the IDT + asm("sidt %0;" : : "m" (sBIOSIDTDescriptor)); + + TRACE("IDT: base: %p, limit: %u\n", sBIOSIDTDescriptor.base, + sBIOSIDTDescriptor.limit); + + // set interrupt gates + #define INTERRUPT_FUNCTION(vector) \ + set_interrupt_gate(vector, &interrupt_function##vector); + INTERRUPT_FUNCTIONS() + #undef INTERRUPT_FUNCTION + + // set the debug IDT + set_debug_idt(); +} + + +void +restore_bios_idt() +{ + set_idt(sBIOSIDTDescriptor); +} + + +void +set_debug_idt() +{ + set_idt(sDebugIDTDescriptor); +} + + +void +interrupts_init_kernel_idt(void* idt, size_t idtSize) +{ + // clear it but copy the descriptors we've set up for the exceptions + memset(idt, 0, idtSize); + memcpy(idt, sDebugIDT, sizeof(sDebugIDT)); + + // load the idt + gdt_idt_descr idtDescriptor; + idtDescriptor.limit = idtSize - 1; + idtDescriptor.base = idt; + set_idt(idtDescriptor); +} Added: haiku/trunk/src/system/boot/platform/bios_ia32/interrupts.h =================================================================== --- haiku/trunk/src/system/boot/platform/bios_ia32/interrupts.h (rev 0) +++ haiku/trunk/src/system/boot/platform/bios_ia32/interrupts.h 2011-06-11 00:08:42 UTC (rev 42092) @@ -0,0 +1,63 @@ +/* + * Copyright 2011, Ingo Weinhold, ingo_weinhold@xxxxxxx + * Distributed under the terms of the MIT License. + */ +#ifndef INTERRUPTS_H +#define INTERRUPTS_H + + +#ifndef _ASSEMBLER + + +#include <sys/cdefs.h> + +#include <SupportDefs.h> + + +struct gdt_idt_descr { + uint16 limit; + void* base; +} _PACKED; + + +__BEGIN_DECLS + + +void interrupts_init(); +void set_debug_idt(); +void restore_bios_idt(); +void interrupts_init_kernel_idt(void* idt, size_t idtSize); + + +__END_DECLS + + +#endif // _ASSEMBLER + +#define INTERRUPT_FUNCTION_ERROR(vector) INTERRUPT_FUNCTION(vector) + +#define INTERRUPT_FUNCTIONS5(vector1, vector2, vector3, vector4, vector5) \ + INTERRUPT_FUNCTION(vector1) \ + INTERRUPT_FUNCTION(vector2) \ + INTERRUPT_FUNCTION(vector3) \ + INTERRUPT_FUNCTION(vector4) \ + INTERRUPT_FUNCTION(vector5) + +#define INTERRUPT_FUNCTIONS() \ + INTERRUPT_FUNCTIONS5(0, 1, 2, 3, 4) \ + INTERRUPT_FUNCTIONS5(5, 6, 7, 8, 9) \ + INTERRUPT_FUNCTION_ERROR(10) \ + INTERRUPT_FUNCTION_ERROR(11) \ + INTERRUPT_FUNCTION_ERROR(12) \ + INTERRUPT_FUNCTION_ERROR(13) \ + INTERRUPT_FUNCTION_ERROR(14) \ + INTERRUPT_FUNCTION(15) \ + INTERRUPT_FUNCTION(16) \ + INTERRUPT_FUNCTION_ERROR(17) \ + INTERRUPT_FUNCTION(18) \ + INTERRUPT_FUNCTION(19) + +#define DEBUG_IDT_SLOT_COUNT 20 + + +#endif // INTERRUPTS_H Added: haiku/trunk/src/system/boot/platform/bios_ia32/interrupts_asm.S =================================================================== --- haiku/trunk/src/system/boot/platform/bios_ia32/interrupts_asm.S (rev 0) +++ haiku/trunk/src/system/boot/platform/bios_ia32/interrupts_asm.S 2011-06-11 00:08:42 UTC (rev 42092) @@ -0,0 +1,46 @@ +/* + * Copyright 2011, Ingo Weinhold, ingo_weinhold@xxxxxxx + * Distributed under the terms of the MIT License. + */ + + +#include <asm_defs.h> + +#include "interrupts.h" + + +// #pragma mark - interrupt functions + + +#define INTERRUPT_FUNCTION(vector) \ +.align 8; \ +FUNCTION(interrupt_function##vector): \ + pushl $0; \ + pusha; \ + pushl $vector; \ + call handle_exception; + +#undef INTERRUPT_FUNCTION_ERROR +#define INTERRUPT_FUNCTION_ERROR(vector) \ +.align 8; \ +FUNCTION(interrupt_function##vector): \ + pusha; \ + pushl $vector; \ + call handle_exception; + +INTERRUPT_FUNCTIONS() + + +// #pragma mark - interrupt functions during exception + + +#undef INTERRUPT_FUNCTION +#define INTERRUPT_FUNCTION(vector) \ +.align 8; \ +FUNCTION(exception_interrupt_function##vector): \ + call handle_exception_exception; + +#undef INTERRUPT_FUNCTION_ERROR +#define INTERRUPT_FUNCTION_ERROR(vector) INTERRUPT_FUNCTION(vector) + +INTERRUPT_FUNCTIONS() Modified: haiku/trunk/src/system/boot/platform/bios_ia32/mmu.cpp =================================================================== --- haiku/trunk/src/system/boot/platform/bios_ia32/mmu.cpp 2011-06-10 22:31:33 UTC (rev 42091) +++ haiku/trunk/src/system/boot/platform/bios_ia32/mmu.cpp 2011-06-11 00:08:42 UTC (rev 42092) @@ -7,21 +7,23 @@ #include "mmu.h" -#include "bios.h" +#include <string.h> + +#include <OS.h> + +#include <arch/cpu.h> +#include <arch_kernel.h> #include <boot/platform.h> #include <boot/stdio.h> #include <boot/kernel_args.h> #include <boot/stage2.h> -#include <arch/cpu.h> -#include <arch_kernel.h> #include <kernel.h> -#include <OS.h> +#include "bios.h" +#include "interrupts.h" -#include <string.h> - /*! The (physical) memory layout of the boot loader is currently as follows: 0x0500 - 0x10000 protected mode stack 0x0500 - 0x09000 real mode stack @@ -58,11 +60,6 @@ // for output to work. -struct gdt_idt_descr { - uint16 limit; - uint32 *base; -} _PACKED; - // memory structure returned by int 0x15, ax 0xe820 struct extended_memory { uint64 base_addr; @@ -491,7 +488,6 @@ TRACE("mmu_init_for_kernel\n"); // set up a new idt { - struct gdt_idt_descr idtDescriptor; uint32 *idt; // find a new idt @@ -504,19 +500,10 @@ gKernelArgs.arch_args.vir_idt = (uint32)get_next_virtual_page(); map_page(gKernelArgs.arch_args.vir_idt, (uint32)idt, kDefaultPageFlags); - // clear it out - uint32* virtualIDT = (uint32*)gKernelArgs.arch_args.vir_idt; - for (int32 i = 0; i < IDT_LIMIT / 4; i++) { - virtualIDT[i] = 0; - } + // initialize it + interrupts_init_kernel_idt((void*)gKernelArgs.arch_args.vir_idt, + IDT_LIMIT); - // load the idt - idtDescriptor.limit = IDT_LIMIT - 1; - idtDescriptor.base = (uint32 *)gKernelArgs.arch_args.vir_idt; - - asm("lidt %0;" - : : "m" (idtDescriptor)); - TRACE("idt at virtual address 0x%lx\n", gKernelArgs.arch_args.vir_idt); } @@ -561,7 +548,7 @@ // load the GDT gdtDescriptor.limit = GDT_LIMIT - 1; - gdtDescriptor.base = (uint32 *)gKernelArgs.arch_args.vir_gdt; + gdtDescriptor.base = (void*)gKernelArgs.arch_args.vir_gdt; asm("lgdt %0;" : : "m" (gdtDescriptor)); Modified: haiku/trunk/src/system/boot/platform/bios_ia32/shell.S =================================================================== --- haiku/trunk/src/system/boot/platform/bios_ia32/shell.S 2011-06-10 22:31:33 UTC (rev 42091) +++ haiku/trunk/src/system/boot/platform/bios_ia32/shell.S 2011-06-11 00:08:42 UTC (rev 42092) @@ -103,7 +103,7 @@ /** Loads %di sectors from floppy disk, starting at head %dh, sector %cx. - * The data is loaded to %es:%bx. On exit, %es:%bx will point immediately + * The data is loaded to %es:%bx. On exit, %es:%bx will point immediately * behind the loaded data, so that you can continue to read in data. * %ax, %cx, %dx, %bp, %di and %si will be clobbered. */ @@ -127,7 +127,7 @@ mov %cx, %si // and remember it pop %cx pop %bx - + load_track: mov %di, %ax // limit the sector count to track boundaries add %cl, %al @@ -292,8 +292,10 @@ mov %ax, %gs mov %ax, %ss - mov $0x10000, %ebp // setup new stack - mov %ebp, %esp + movl $0x10000, %esp // setup new stack + pushl $0 // terminate stack frame chain (next frame and + pushl $0 // return address) + mov %esp, %ebp call _start Modified: haiku/trunk/src/system/boot/platform/bios_ia32/start.cpp =================================================================== --- haiku/trunk/src/system/boot/platform/bios_ia32/start.cpp 2011-06-10 22:31:33 UTC (rev 42091) +++ haiku/trunk/src/system/boot/platform/bios_ia32/start.cpp 2011-06-11 00:08:42 UTC (rev 42092) @@ -20,6 +20,7 @@ #include "cpu.h" #include "debug.h" #include "hpet.h" +#include "interrupts.h" #include "keyboard.h" #include "mmu.h" #include "multiboot.h" @@ -84,6 +85,10 @@ smp_init_other_cpus(); debug_cleanup(); mmu_init_for_kernel(); + + // We're about to enter the kernel -- disable console output. + stdout = NULL; + smp_boot_other_cpus(); dprintf("kernel entry at %lx\n", [... truncated: 33 lines follow ...]