* 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. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42092 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
8c3c117201
commit
2e8aa19c63
@ -21,7 +21,8 @@ KernelMergeObject boot_platform_bios_ia32.o :
|
||||
shell.S
|
||||
start.cpp
|
||||
debug.cpp
|
||||
bios.S
|
||||
bios.cpp
|
||||
bios_asm.S
|
||||
console.cpp
|
||||
serial.cpp
|
||||
devices.cpp
|
||||
@ -37,6 +38,8 @@ KernelMergeObject boot_platform_bios_ia32.o :
|
||||
video.cpp
|
||||
apm.cpp
|
||||
hpet.cpp
|
||||
interrupts.cpp
|
||||
interrupts_asm.S
|
||||
|
||||
# VESA/DDC EDID
|
||||
decode_edid.c
|
||||
|
22
src/system/boot/platform/bios_ia32/bios.cpp
Normal file
22
src/system/boot/platform/bios_ia32/bios.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* 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();
|
||||
|
||||
}
|
@ -158,11 +158,11 @@ _real_code_segment:
|
||||
//--------------------------------------------------------------
|
||||
|
||||
|
||||
/*! void call_bios(uint8 num, struct bios_regs *regs)
|
||||
/*! 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)
|
||||
FUNCTION(call_bios_internal)
|
||||
pushal
|
||||
pushfl
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <boot/platform.h>
|
||||
@ -26,6 +25,33 @@ static char sBuffer[16384];
|
||||
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.
|
||||
@ -54,26 +80,29 @@ panic(const char *format, ...)
|
||||
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 @@ debug_cleanup(void)
|
||||
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 @@ debug_cleanup(void)
|
||||
gKernelArgs.debug_size = sBufferPosition;
|
||||
}
|
||||
}
|
||||
|
||||
sPostCleanup = true;
|
||||
}
|
||||
|
@ -6,6 +6,8 @@
|
||||
#define DEBUG_H
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
|
249
src/system/boot/platform/bios_ia32/interrupts.cpp
Normal file
249
src/system/boot/platform/bios_ia32/interrupts.cpp
Normal file
@ -0,0 +1,249 @@
|
||||
/*
|
||||
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* 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);
|
||||
}
|
63
src/system/boot/platform/bios_ia32/interrupts.h
Normal file
63
src/system/boot/platform/bios_ia32/interrupts.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* 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
|
46
src/system/boot/platform/bios_ia32/interrupts_asm.S
Normal file
46
src/system/boot/platform/bios_ia32/interrupts_asm.S
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* 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()
|
@ -7,19 +7,21 @@
|
||||
|
||||
|
||||
#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 <string.h>
|
||||
#include "bios.h"
|
||||
#include "interrupts.h"
|
||||
|
||||
|
||||
/*! The (physical) memory layout of the boot loader is currently as follows:
|
||||
@ -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 @@ mmu_init_for_kernel(void)
|
||||
TRACE("mmu_init_for_kernel\n");
|
||||
// set up a new idt
|
||||
{
|
||||
struct gdt_idt_descr idtDescriptor;
|
||||
uint32 *idt;
|
||||
|
||||
// find a new idt
|
||||
@ -504,18 +500,9 @@ mmu_init_for_kernel(void)
|
||||
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;
|
||||
}
|
||||
|
||||
// load the idt
|
||||
idtDescriptor.limit = IDT_LIMIT - 1;
|
||||
idtDescriptor.base = (uint32 *)gKernelArgs.arch_args.vir_idt;
|
||||
|
||||
asm("lidt %0;"
|
||||
: : "m" (idtDescriptor));
|
||||
// initialize it
|
||||
interrupts_init_kernel_idt((void*)gKernelArgs.arch_args.vir_idt,
|
||||
IDT_LIMIT);
|
||||
|
||||
TRACE("idt at virtual address 0x%lx\n", gKernelArgs.arch_args.vir_idt);
|
||||
}
|
||||
@ -561,7 +548,7 @@ mmu_init_for_kernel(void)
|
||||
|
||||
// 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));
|
||||
|
@ -103,7 +103,7 @@ start_loader:
|
||||
|
||||
|
||||
/** 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 @@ load_sectors:
|
||||
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 @@ _protected_code_segment:
|
||||
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
|
||||
|
||||
|
@ -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 @@ platform_start_kernel(void)
|
||||
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",
|
||||
@ -128,6 +133,7 @@ _start(void)
|
||||
|
||||
serial_init();
|
||||
serial_enable();
|
||||
interrupts_init();
|
||||
console_init();
|
||||
cpu_init();
|
||||
mmu_init();
|
||||
|
@ -20,7 +20,8 @@ UsePrivateHeaders [ FDirName storage ] ;
|
||||
local bios_ia32_src =
|
||||
start.cpp
|
||||
debug.cpp
|
||||
bios.S
|
||||
bios.cpp
|
||||
bios_asm.S
|
||||
console.cpp
|
||||
serial.cpp
|
||||
keyboard.cpp
|
||||
@ -34,6 +35,8 @@ local bios_ia32_src =
|
||||
video.cpp
|
||||
hpet.cpp
|
||||
apm.cpp
|
||||
interrupts.cpp
|
||||
interrupts_asm.S
|
||||
;
|
||||
|
||||
local bios_ia32_edid_src =
|
||||
|
Loading…
Reference in New Issue
Block a user