[haiku-commits] BRANCH xyzzy-github.x86_64 - src/system/boot/platform/bios_ia32 src/system/kernel/arch/x86_64 headers/private/kernel/arch/x86_64 src/system/kernel/arch/x86

  • From: xyzzy-github.x86_64 <community@xxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 26 Jun 2012 12:48:58 +0200 (CEST)

added 5 changesets to branch 'refs/remotes/xyzzy-github/x86_64'
old head: f69dd487b1c4e0a3f35d6477e9a6720315e89f35
new head: b8a9a3a16073d8f474ee3415e208d04f4b58b4b0

----------------------------------------------------------------------------

5a17b2f: Forgot to change driver_settings_file to use FixedWidthPointer.

a820f12: Style fixes to elf.cpp.

e5fc2bf: Implemented long mode setup/switch code, the bootloader can now start 
the 64-bit kernel!
  
  The setup procedure is fairly simple: create a 64-bit GDT and 64-bit page
  tables that include all kernel mappings from the 32-bit address space, but at
  the correct 64-bit address, then go through kernel_args and changes all 
virtual
  addresses to 64-bit addresses, and finally switch to long mode and jump to the
  kernel.

991e5be: Pass correct kernel_args address to the kernel.

b8a9a3a: Copied the x86 debug console functions to x86_64.
  
  Note that this is only temporary so that I have serial output from the kernel,
  the x86 and x86_64 versions will be merged later.

                                      [ Alex Smith <alex@xxxxxxxxxxxxxxxx> ]

----------------------------------------------------------------------------

19 files changed, 758 insertions(+), 32 deletions(-)
headers/private/kernel/arch/x86/arch_kernel_args.h |   10 +-
headers/private/kernel/arch/x86_64/descriptors.h   |  149 ++++++++
headers/private/kernel/boot/driver_settings.h      |    6 +-
src/system/boot/loader/elf.cpp                     |   14 +-
src/system/boot/platform/bios_ia32/Jamfile         |    2 +
src/system/boot/platform/bios_ia32/long.cpp        |  290 ++++++++++++++++
src/system/boot/platform/bios_ia32/long.h          |   18 +
src/system/boot/platform/bios_ia32/long_asm.S      |   75 ++++
src/system/boot/platform/bios_ia32/mmu.cpp         |   55 ++-
src/system/boot/platform/bios_ia32/mmu.h           |    6 +
src/system/boot/platform/bios_ia32/smp.cpp         |    2 +-
src/system/boot/platform/bios_ia32/start.cpp       |    7 +
src/system/boot/platform/pxe_ia32/Jamfile          |    2 +
src/system/kernel/arch/x86/arch_cpu.cpp            |    2 +-
src/system/kernel/arch/x86/arch_int.cpp            |    2 +-
.../arch/x86/paging/32bit/X86PagingMethod32Bit.cpp |    4 +-
.../arch/x86/paging/pae/X86PagingMethodPAE.cpp     |    3 +-
src/system/kernel/arch/x86_64/arch_cpu.cpp         |    2 +
.../kernel/arch/x86_64/arch_debug_console.cpp      |  141 +++++++-

############################################################################

Commit:      5a17b2f1b272c71940a67474fc029fa5cf40cff6

Author:      Alex Smith <alex@xxxxxxxxxxxxxxxx>
Date:        Tue Jun 26 09:54:37 2012 UTC

Forgot to change driver_settings_file to use FixedWidthPointer.

----------------------------------------------------------------------------

diff --git a/headers/private/kernel/boot/driver_settings.h 
b/headers/private/kernel/boot/driver_settings.h
index bee57df..03d0d03 100644
--- a/headers/private/kernel/boot/driver_settings.h
+++ b/headers/private/kernel/boot/driver_settings.h
@@ -13,8 +13,8 @@
 struct driver_settings_file {
        FixedWidthPointer<struct driver_settings_file> next;
        char    name[B_OS_NAME_LENGTH];
-       char    *buffer;
-       size_t  size;
-};
+       FixedWidthPointer<char> buffer;
+       uint32  size;
+} _PACKED;
 
 #endif /* KERNEL_BOOT_DRIVER_SETTINGS_H */

############################################################################

Commit:      a820f12943d570cfcb6dbb78781dc587f56e0da8

Author:      Alex Smith <alex@xxxxxxxxxxxxxxxx>
Date:        Tue Jun 26 09:59:03 2012 UTC

Style fixes to elf.cpp.

----------------------------------------------------------------------------

diff --git a/src/system/boot/loader/elf.cpp b/src/system/boot/loader/elf.cpp
index 84a1d0a..8494ff7 100644
--- a/src/system/boot/loader/elf.cpp
+++ b/src/system/boot/loader/elf.cpp
@@ -76,11 +76,11 @@ struct ELF32Class {
 
        static inline status_t
        AllocateRegion(AddrType* _address, AddrType size, uint8 protection,
-               void **_mappedAddress)
+               void** _mappedAddress)
        {
                status_t status = platform_allocate_region((void**)_address, 
size,
                        protection, false);
-               if (status < B_OK)
+               if (status != B_OK)
                        return status;
 
                *_mappedAddress = (void*)*_address;
@@ -123,7 +123,7 @@ struct ELF64Class {
 
                status_t status = platform_allocate_region(&address, size, 
protection,
                        false);
-               if (status < B_OK)
+               if (status != B_OK)
                        return status;
 
                *_mappedAddress = address;
@@ -282,7 +282,7 @@ ELFLoader<Class>::Load(int fd, preloaded_image* _image)
        // can automatically allocate an address, but shall prefer the specified
        // base address.
        if (Class::AllocateRegion(&firstRegion->start, totalSize,
-                       B_READ_AREA | B_WRITE_AREA, &mappedRegion) < B_OK) {
+                       B_READ_AREA | B_WRITE_AREA, &mappedRegion) != B_OK) {
                status = B_NO_MEMORY;
                goto error1;
        }
@@ -379,7 +379,7 @@ ELFLoader<Class>::Relocate(preloaded_image* _image)
                        (int)image->rel_len / (int)sizeof(RelType)));
 
                status = boot_arch_elf_relocate_rel(image, image->rel, 
image->rel_len);
-               if (status < B_OK)
+               if (status != B_OK)
                        return status;
        }
 
@@ -398,7 +398,7 @@ ELFLoader<Class>::Relocate(preloaded_image* _image)
                        status = boot_arch_elf_relocate_rela(image, 
(RelaType*)pltrel,
                                image->pltrel_len);
                }
-               if (status < B_OK)
+               if (status != B_OK)
                        return status;
        }
 
@@ -407,7 +407,7 @@ ELFLoader<Class>::Relocate(preloaded_image* _image)
                        (int)image->rela_len / (int)sizeof(RelaType)));
                status = boot_arch_elf_relocate_rela(image, image->rela,
                        image->rela_len);
-               if (status < B_OK)
+               if (status != B_OK)
                        return status;
        }
 

############################################################################

Commit:      e5fc2bfcab8c15a3ff7d33c358f9aa82ed73c823

Author:      Alex Smith <alex@xxxxxxxxxxxxxxxx>
Date:        Tue Jun 26 10:01:23 2012 UTC

Implemented long mode setup/switch code, the bootloader can now start the 
64-bit kernel!

The setup procedure is fairly simple: create a 64-bit GDT and 64-bit page
tables that include all kernel mappings from the 32-bit address space, but at
the correct 64-bit address, then go through kernel_args and changes all virtual
addresses to 64-bit addresses, and finally switch to long mode and jump to the
kernel.

----------------------------------------------------------------------------

diff --git a/headers/private/kernel/arch/x86/arch_kernel_args.h 
b/headers/private/kernel/arch/x86/arch_kernel_args.h
index de17c7c..7e6c967 100644
--- a/headers/private/kernel/arch/x86/arch_kernel_args.h
+++ b/headers/private/kernel/arch/x86/arch_kernel_args.h
@@ -26,15 +26,15 @@ typedef struct {
        uint32  system_time_cv_factor;
        uint64  cpu_clock_speed;
        uint32  phys_pgdir;
-       uint32  vir_pgdir;
+       uint64  vir_pgdir;
        uint32  num_pgtables;
        uint32  pgtables[MAX_BOOT_PTABLES];
-       uint32  virtual_end;
+       uint64  virtual_end;
        uint32  phys_idt;
-       uint32  vir_idt;
+       uint64  vir_idt;
        uint32  phys_gdt;
-       uint32  vir_gdt;
-       uint32  page_hole;
+       uint64  vir_gdt;
+       uint64  page_hole;
        // smp stuff
        uint32  apic_time_cv_factor; // apic ticks per second
        uint32  apic_phys;
diff --git a/headers/private/kernel/arch/x86_64/descriptors.h 
b/headers/private/kernel/arch/x86_64/descriptors.h
new file mode 100644
index 0000000..a1850f0
--- /dev/null
+++ b/headers/private/kernel/arch/x86_64/descriptors.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2012, Alex Smith, alex@xxxxxxxxxxxxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef _KERNEL_ARCH_X86_64_DESCRIPTORS_H
+#define _KERNEL_ARCH_X86_64_DESCRIPTORS_H
+
+
+// Segment definitions.
+// Note that the ordering of these is important to SYSCALL/SYSRET.
+#define KERNEL_CODE_SEG                0x08
+#define KERNEL_DATA_SEG                0x10
+#define USER_DATA_SEG          0x18
+#define USER_CODE_SEG          0x20
+
+
+#ifndef _ASSEMBLER
+
+
+#define TSS_BASE_SEGMENT       5
+#define TLS_BASE_SEGMENT       (TSS_BASE_SEGMENT + smp_get_num_cpus())
+
+
+// Structure of a segment descriptor.
+struct segment_descriptor {
+       uint32 limit0 : 16;
+       uint32 base0 : 24;
+       uint32 type : 4;
+       uint32 desc_type : 1;
+       uint32 dpl : 2;
+       uint32 present : 1;
+       uint32 limit1 : 4;
+       uint32 available : 1;
+       uint32 long_mode : 1;
+       uint32 d_b : 1;
+       uint32 granularity : 1;
+       uint32 base1 : 8;
+} _PACKED;
+
+// Structure of a TSS segment descriptor.
+struct tss_descriptor {
+       uint32 limit0 : 16;
+       uint32 base0 : 24;
+       uint32 type : 4;
+       uint32 desc_type : 1;
+       uint32 dpl : 2;
+       uint32 present : 1;
+       uint32 limit1 : 4;
+       uint32 available : 1;
+       uint32 unused1 : 2;
+       uint32 granularity : 1;
+       uint32 base1 : 8;
+       uint32 base2 : 32;
+       uint32 unused2 : 32;
+} _PACKED;
+
+// Structure of an interrupt descriptor.
+struct interrupt_descriptor {
+       uint32 base0 : 16;
+       uint32 sel : 16;
+       uint32 ist : 3;
+       uint32 unused : 5;
+       uint32 flags : 8;
+       uint32 base1 : 16;
+       uint32 base2 : 32;
+       uint32 reserved : 32;
+} _PACKED;
+
+enum descriptor_privilege_levels {
+       DPL_KERNEL = 0,
+       DPL_USER = 3,
+};
+
+enum descriptor_types {
+       // Code/data descriptor types.
+       DT_CODE_EXECUTE_ONLY = 0x8,
+       DT_CODE_ACCESSED = 0x9,
+       DT_CODE_READABLE = 0xa,
+       DT_CODE_CONFORM = 0xc,
+       DT_DATA_READ_ONLY = 0x0,
+       DT_DATA_ACCESSED = 0x1,
+       DT_DATA_WRITEABLE = 0x2,
+       DT_DATA_EXPANSION_DOWN = 0x4,
+
+       // System descriptor types.
+       DT_TSS = 9,
+
+       // Descriptor types
+       DT_SYSTEM_SEGMENT = 0,
+       DT_CODE_DATA_SEGMENT = 1,
+};
+
+
+static inline void
+clear_segment_descriptor(segment_descriptor* desc)
+{
+       *(uint64*)desc = 0;
+}
+
+
+static inline void
+set_segment_descriptor(segment_descriptor* desc, uint8 type, uint8 dpl)
+{
+       clear_segment_descriptor(desc);
+
+       // In 64-bit mode the CPU ignores the base/limit of code/data segments,
+       // it always treats base as 0 and does no limit checks.
+       desc->base0 = 0;
+       desc->base1 = 0;
+       desc->limit0 = 0xFFFF;
+       desc->limit1 = 0xF;
+       desc->granularity = 1;
+
+       desc->type = type;
+       desc->desc_type = DT_CODE_DATA_SEGMENT;
+       desc->dpl = dpl;
+       desc->present = 1;
+
+       desc->long_mode = (type & DT_CODE_EXECUTE_ONLY) ? 1 : 0;
+               // Must be set to 1 for code segments only.
+}
+
+
+static inline void
+set_tss_descriptor(segment_descriptor* _desc, uint64 base, uint32 limit)
+{
+       clear_segment_descriptor(_desc);
+       clear_segment_descriptor(&_desc[1]);
+
+       // The TSS descriptor is a special format in 64-bit mode, it is 16 bytes
+       // instead of 8.
+       tss_descriptor* desc = (tss_descriptor*)_desc;
+
+       desc->base0 = base & 0xffffff;
+       desc->base1 = ((base) >> 24) & 0xff;
+       desc->base2 = ((base) >> 32);
+       desc->limit0 = limit & 0xffff;
+       desc->limit1 = (limit >> 16) & 0xf;
+
+       desc->present = 1;
+       desc->type = DT_TSS;
+       desc->desc_type = DT_SYSTEM_SEGMENT;
+       desc->dpl = DPL_KERNEL;
+}
+
+
+#endif /* _ASSEMBLER */
+
+#endif /* _KERNEL_ARCH_X86_64_DESCRIPTORS_H */
diff --git a/src/system/boot/platform/bios_ia32/Jamfile 
b/src/system/boot/platform/bios_ia32/Jamfile
index 6c0c273..347d2b4 100644
--- a/src/system/boot/platform/bios_ia32/Jamfile
+++ b/src/system/boot/platform/bios_ia32/Jamfile
@@ -40,6 +40,8 @@ BootMergeObject boot_platform_bios_ia32.o :
        hpet.cpp
        interrupts.cpp
        interrupts_asm.S
+       long.cpp
+       long_asm.S
 
        # VESA/DDC EDID
        decode_edid.c
diff --git a/src/system/boot/platform/bios_ia32/long.cpp 
b/src/system/boot/platform/bios_ia32/long.cpp
new file mode 100644
index 0000000..829e2ad
--- /dev/null
+++ b/src/system/boot/platform/bios_ia32/long.cpp
@@ -0,0 +1,290 @@
+/*
+ * Copyright 2012, Alex Smith, alex@xxxxxxxxxxxxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+
+
+// Stop this from being included, it conflicts with the x86_64 version.
+#define _KERNEL_ARCH_x86_DESCRIPTORS_H
+
+
+#include "long.h"
+
+#include <KernelExport.h>
+
+#include <arch/x86_64/descriptors.h>
+#include <arch_system_info.h>
+#include <boot/platform.h>
+#include <boot/heap.h>
+#include <boot/stage2.h>
+#include <boot/stdio.h>
+#include <kernel.h>
+
+#include "debug.h"
+#include "mmu.h"
+
+
+struct gdt_idt_descr {
+       uint16 limit;
+       addr_t base;
+} _PACKED;
+
+
+/*! Convert a 32-bit address to a 64-bit address. */
+static inline uint64
+fix_address(uint64 address)
+{
+       return address - KERNEL_BASE + KERNEL_BASE_64BIT;
+}
+
+
+template<typename Type>
+inline void
+fix_address(FixedWidthPointer<Type>& p)
+{
+       if(p != NULL)
+               p.SetTo(fix_address(p.Get()));
+}
+
+
+static void
+long_gdt_init()
+{
+       // Allocate memory for the GDT.
+       segment_descriptor* gdt = (segment_descriptor*)
+               mmu_allocate_page(&gKernelArgs.arch_args.phys_gdt);
+       gKernelArgs.arch_args.vir_gdt = fix_address((addr_t)gdt);
+
+       dprintf("GDT at phys 0x%lx, virt 0x%llx\n", 
gKernelArgs.arch_args.phys_gdt,
+               gKernelArgs.arch_args.vir_gdt);
+
+       clear_segment_descriptor(&gdt[0]);
+
+       // Set up code/data segments (TSS segments set up later in the kernel).
+       set_segment_descriptor(&gdt[KERNEL_CODE_SEG / 8], DT_CODE_EXECUTE_ONLY,
+               DPL_KERNEL);
+       set_segment_descriptor(&gdt[KERNEL_DATA_SEG / 8], DT_DATA_WRITEABLE,
+               DPL_KERNEL);
+       set_segment_descriptor(&gdt[USER_CODE_SEG / 8], DT_CODE_EXECUTE_ONLY,
+               DPL_USER);
+       set_segment_descriptor(&gdt[USER_DATA_SEG / 8], DT_DATA_WRITEABLE,
+               DPL_USER);
+}
+
+
+static void
+long_idt_init()
+{
+       interrupt_descriptor* idt = (interrupt_descriptor*)
+               mmu_allocate_page(&gKernelArgs.arch_args.phys_idt);
+       gKernelArgs.arch_args.vir_idt = fix_address((addr_t)idt);
+
+       dprintf("IDT at phys 0x%lx, virt 0x%llx\n", 
gKernelArgs.arch_args.phys_idt,
+               gKernelArgs.arch_args.vir_idt);
+
+       // The 32-bit kernel gets an IDT with the loader's exception handlers 
until
+       // it can set up its own. Can't do that here because they won't work 
after
+       // switching to long mode. Therefore, just clear the IDT and leave the
+       // kernel to set it up.
+       memset(idt, 0, B_PAGE_SIZE);
+}
+
+
+static void
+long_mmu_init()
+{
+       addr_t physicalAddress;
+
+       // Allocate the top level PML4.
+       uint64* pml4 = 
(uint64*)mmu_allocate_page(&gKernelArgs.arch_args.phys_pgdir);
+       memset(pml4, 0, B_PAGE_SIZE);
+       gKernelArgs.arch_args.vir_pgdir = (uint64)(addr_t)pml4;
+
+       // Identity map the first 1GB of memory, do so using large pages.
+
+       uint64* pdpt = (uint64*)mmu_allocate_page(&physicalAddress);
+       memset(pdpt, 0, B_PAGE_SIZE);
+       pml4[0] = physicalAddress | 0x3;
+
+       uint64* pageDir = (uint64*)mmu_allocate_page(&physicalAddress);
+       memset(pageDir, 0, B_PAGE_SIZE);
+       pdpt[0] = physicalAddress | 0x3;
+
+       for (uint32 i = 0; i < 512; i++) {
+               pageDir[i] = (i * 0x200000) | 0x83;
+       }
+
+       // Allocate tables for the kernel mappings.
+
+       pdpt = (uint64*)mmu_allocate_page(&physicalAddress);
+       memset(pdpt, 0, B_PAGE_SIZE);
+       pml4[511] = physicalAddress | 0x3;
+
+       pageDir = (uint64*)mmu_allocate_page(&physicalAddress);
+       memset(pageDir, 0, B_PAGE_SIZE);
+       pdpt[510] = physicalAddress | 0x3;
+
+       // Store the virtual memory usage information.
+       gKernelArgs.virtual_allocated_range[0].start = KERNEL_BASE_64BIT;
+       gKernelArgs.virtual_allocated_range[0].size = mmu_get_virtual_usage();
+       gKernelArgs.num_virtual_allocated_ranges = 1;
+
+       // We can now allocate page tables and duplicate the mappings across 
from
+       // the 32-bit address space to them.
+       uint64* pageTable = NULL;
+       for (uint32 i = 0; i < gKernelArgs.virtual_allocated_range[0].size
+                       / B_PAGE_SIZE; i++) {
+               if ((i % 512) == 0) {
+                       pageTable = 
(uint64*)mmu_allocate_page(&physicalAddress);
+                       memset(pageTable, 0, B_PAGE_SIZE);
+                       pageDir[i / 512] = physicalAddress | 0x3;
+
+                       // Just performed another virtual allocation, account 
for it.
+                       gKernelArgs.virtual_allocated_range[0].size += 
B_PAGE_SIZE;
+               }
+
+               // Get the physical address to map.
+               if (!mmu_get_virtual_mapping(KERNEL_BASE + (i * B_PAGE_SIZE),
+                               &physicalAddress))
+                       continue;
+
+               pageTable[i % 512] = physicalAddress | 0x3;
+       }
+
+       gKernelArgs.arch_args.virtual_end = ROUNDUP(KERNEL_BASE_64BIT
+               + gKernelArgs.virtual_allocated_range[0].size, 0x200000);
+
+       // Sort the address ranges.
+       sort_address_ranges(gKernelArgs.physical_memory_range,
+               gKernelArgs.num_physical_memory_ranges);
+       sort_address_ranges(gKernelArgs.physical_allocated_range,
+               gKernelArgs.num_physical_allocated_ranges);
+       sort_address_ranges(gKernelArgs.virtual_allocated_range,
+               gKernelArgs.num_virtual_allocated_ranges);
+
+       dprintf("phys memory ranges:\n");
+       for (uint32 i = 0; i < gKernelArgs.num_physical_memory_ranges; i++) {
+               dprintf("    base %#018" B_PRIx64 ", length %#018" B_PRIx64 
"\n",
+                       gKernelArgs.physical_memory_range[i].start,
+                       gKernelArgs.physical_memory_range[i].size);
+       }
+
+       dprintf("allocated phys memory ranges:\n");
+       for (uint32 i = 0; i < gKernelArgs.num_physical_allocated_ranges; i++) {
+               dprintf("    base %#018" B_PRIx64 ", length %#018" B_PRIx64 
"\n",
+                       gKernelArgs.physical_allocated_range[i].start,
+                       gKernelArgs.physical_allocated_range[i].size);
+       }
+
+       dprintf("allocated virt memory ranges:\n");
+       for (uint32 i = 0; i < gKernelArgs.num_virtual_allocated_ranges; i++) {
+               dprintf("    base %#018" B_PRIx64 ", length %#018" B_PRIx64 
"\n",
+                       gKernelArgs.virtual_allocated_range[i].start,
+                       gKernelArgs.virtual_allocated_range[i].size);
+       }
+}
+
+
+static void
+convert_preloaded_image(preloaded_elf64_image* image)
+{
+       fix_address(image->next);
+       fix_address(image->name);
+       fix_address(image->debug_string_table);
+       fix_address(image->syms);
+       fix_address(image->rel);
+       fix_address(image->rela);
+       fix_address(image->pltrel);
+       fix_address(image->debug_symbols);
+}
+
+
+/*!    Convert all addresses in kernel_args to 64-bit addresses. */
+static void
+convert_kernel_args()
+{
+       fix_address(gKernelArgs.boot_volume);
+       fix_address(gKernelArgs.vesa_modes);
+       fix_address(gKernelArgs.edid_info);
+       fix_address(gKernelArgs.debug_output);
+       fix_address(gKernelArgs.boot_splash);
+       fix_address(gKernelArgs.arch_args.apic);
+       fix_address(gKernelArgs.arch_args.hpet);
+
+       convert_preloaded_image(static_cast<preloaded_elf64_image*>(
+               gKernelArgs.kernel_image.Pointer()));
+       fix_address(gKernelArgs.kernel_image);
+
+       // Iterate over the preloaded images. Must save the next address before
+       // converting, as the next pointer will be converted.
+       preloaded_image* image = gKernelArgs.preloaded_images;
+       fix_address(gKernelArgs.preloaded_images);
+       while (image) {
+               preloaded_image* next = image->next;
+               
convert_preloaded_image(static_cast<preloaded_elf64_image*>(image));
+               image = next;
+       }
+
+       // Set correct kernel stack addresses.
+       for (uint32 i = 0; i < gKernelArgs.num_cpus; i++) {
+               gKernelArgs.cpu_kstack[i].start
+                       = fix_address(gKernelArgs.cpu_kstack[i].start);
+       }
+
+       // Fix driver settings files.
+       driver_settings_file* file = gKernelArgs.driver_settings;
+       fix_address(gKernelArgs.driver_settings);
+       while (file) {
+               driver_settings_file* next = file->next;
+               fix_address(file->next);
+               fix_address(file->buffer);
+               file = next;
+       }
+}
+
+
+void
+long_start_kernel()
+{
+       // Check whether long mode is supported.
+       cpuid_info info;
+       get_current_cpuid(&info, 0x80000001);
+       if ((info.regs.edx & (1<<29)) == 0)
+               panic("64-bit kernel requires a 64-bit CPU");
+
+       preloaded_elf64_image *image = static_cast<preloaded_elf64_image *>(
+               gKernelArgs.kernel_image.Pointer());
+
+       // TODO: x86_64 SMP, disable for now.
+       gKernelArgs.num_cpus = 1;
+
+       long_gdt_init();
+       long_idt_init();
+       long_mmu_init();
+       convert_kernel_args();
+
+       debug_cleanup();
+
+       // Calculate the arguments for long_enter_kernel().
+       uint64 entry = image->elf_header.e_entry;
+       uint64 stackTop = gKernelArgs.cpu_kstack[0].start
+               + gKernelArgs.cpu_kstack[0].size;
+       uint64 kernelArgs = fix_address((addr_t)&gKernelArgs);
+
+       dprintf("kernel entry at 0x%llx, stack 0x%llx, args 0x%llx\n", entry,
+               stackTop, kernelArgs);
+
+       // We're about to enter the kernel -- disable console output.
+       stdout = NULL;
+
+       // Load the new GDT. The physical address is used because 
long_enter_kernel
+       // disables 32-bit paging.
+       gdt_idt_descr gdtr = { GDT_LIMIT - 1, gKernelArgs.arch_args.phys_gdt };
+       asm volatile("lgdt %0" :: "m"(gdtr));
+
+       // Enter the kernel!
+       long_enter_kernel(gKernelArgs.arch_args.phys_pgdir, entry, stackTop,
+               kernelArgs, 0);
+       panic("Shouldn't get here");
+}
+
diff --git a/src/system/boot/platform/bios_ia32/long.h 
b/src/system/boot/platform/bios_ia32/long.h
new file mode 100644
index 0000000..de2a039
--- /dev/null
+++ b/src/system/boot/platform/bios_ia32/long.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2012, Alex Smith, alex@xxxxxxxxxxxxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef LONG_H
+#define LONG_H
+
+
+#include <SupportDefs.h>
+
+
+extern "C" void long_enter_kernel(uint32 pml4, uint64 entry, uint64 stackTop,
+       uint64 kernelArgs, int currentCPU);
+
+extern void long_start_kernel();
+
+
+#endif /* LONG_H */
diff --git a/src/system/boot/platform/bios_ia32/long_asm.S 
b/src/system/boot/platform/bios_ia32/long_asm.S
new file mode 100644
index 0000000..d22355c
--- /dev/null
+++ b/src/system/boot/platform/bios_ia32/long_asm.S
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2012, Alex Smith, alex@xxxxxxxxxxxxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+
+
+#include <asm_defs.h>
+
+#include <arch/x86_64/descriptors.h>
+
+
+.code32
+
+
+/*!    void long_enter_kernel(uint32 pml4, uint64 entry, uint64 stackTop,
+               uint64 kernelArgs, int currentCPU);
+*/
+FUNCTION(long_enter_kernel):
+       // Currently running with 32-bit paging tables at an identity mapped
+       // address. To switch to 64-bit paging we must first disable 32-bit 
paging,
+       // otherwise loading the new CR3 will fault.
+       movl    %cr0, %eax
+       andl    $~(1<<31), %eax
+       movl    %eax, %cr0
+
+       // Enable PAE.
+       movl    %cr4, %eax
+       orl             $(1<<5), %eax
+       movl    %eax, %cr4
+
+       // Point CR3 to the kernel's PML4.
+       movl    4(%esp), %eax
+       movl    %eax, %cr3
+
+       // Enable long mode by setting EFER.LME.
+       movl    $0xC0000080, %ecx
+       rdmsr
+       orl             $(1<<8), %eax
+       wrmsr
+
+       // Re-enable paging, which will put us in compatibility mode as we are
+       // currently in a 32-bit code segment.
+       movl    %cr0, %ecx
+       orl             $(1<<31), %ecx
+       movl    %ecx, %cr0
+
+       // Jump into the 64-bit code segment.
+       ljmp    $KERNEL_CODE_SEG, $.Llmode
+.align 8
+.code64
+.Llmode:
+       // Set data segments.
+       mov             $KERNEL_DATA_SEG, %ax
+       mov             %ax, %ss
+       mov             %ax, %ds
+       mov             %ax, %es
+       mov             %ax, %fs
+       mov             %ax, %gs
+
+       // Clear the high 32 bits of RSP.
+       movl    %esp, %esp
+
+       // Get the entry point address, arguments and new stack pointer.
+       movq    8(%rsp), %rax
+       movq    24(%rsp), %rdi
+       movl    32(%rsp), %esi
+       movq    16(%rsp), %rsp
+
+       // Clear the stack frame/RFLAGS.
+       xorq    %rbp, %rbp
+       push    $0
+       popf
+
+       // Call the kernel entry point.
+       call    *%rax
diff --git a/src/system/boot/platform/bios_ia32/mmu.cpp 
b/src/system/boot/platform/bios_ia32/mmu.cpp
index cfed3de..93d1a1f 100644
--- a/src/system/boot/platform/bios_ia32/mmu.cpp
+++ b/src/system/boot/platform/bios_ia32/mmu.cpp
@@ -419,6 +419,24 @@ mmu_allocate(void *virtualAddress, size_t size)
 }
 
 
+/*!    Allocates a single page and returns both its virtual and physical
+       addresses.
+*/
+void *
+mmu_allocate_page(addr_t *_physicalAddress)
+{
+       addr_t virt = get_next_virtual_page();
+       addr_t phys = get_next_physical_page();
+
+       map_page(virt, phys, kDefaultPageFlags);
+
+       if (_physicalAddress)
+               *_physicalAddress = phys;
+
+       return (void *)virt;
+}
+
+
 /*!    Allocates the given physical range.
        \return \c true, if the range could be allocated, \c false otherwise.
 */
@@ -478,6 +496,35 @@ mmu_free(void *virtualAddress, size_t size)
 }
 
 
+size_t
+mmu_get_virtual_usage()
+{
+       return sNextVirtualAddress - KERNEL_BASE;
+}
+
+
+bool
+mmu_get_virtual_mapping(addr_t virtualAddress, addr_t *_physicalAddress)
+{
+       if (virtualAddress < KERNEL_BASE) {
+               panic("mmu_get_virtual_mapping: asked to lookup invalid page 
%p!\n",
+                       (void *)virtualAddress);
+       }
+
+       uint32 *pageTable = (uint32 *)(sPageDirectory[virtualAddress
+               / (B_PAGE_SIZE * 1024)] & 0xfffff000);
+       uint32 tableEntry = pageTable[(virtualAddress % (B_PAGE_SIZE * 1024))
+               / B_PAGE_SIZE];
+
+       if ((tableEntry & (1<<0)) != 0) {
+               *_physicalAddress = tableEntry & 0xFFFFF000;
+               return true;
+       } else {
+               return false;
+       }
+}
+
+
 /*!    Sets up the final and kernel accessible GDT and IDT tables.
        BIOS calls won't work any longer after this function has
        been called.
@@ -501,10 +548,10 @@ mmu_init_for_kernel(void)
                map_page(gKernelArgs.arch_args.vir_idt, (uint32)idt, 
kDefaultPageFlags);
 
                // initialize it
-               interrupts_init_kernel_idt((void*)gKernelArgs.arch_args.vir_idt,
+               
interrupts_init_kernel_idt((void*)(addr_t)gKernelArgs.arch_args.vir_idt,
                        IDT_LIMIT);
 
-               TRACE("idt at virtual address 0x%lx\n", 
gKernelArgs.arch_args.vir_idt);
+               TRACE("idt at virtual address 0x%llx\n", 
gKernelArgs.arch_args.vir_idt);
        }
 
        // set up a new gdt
@@ -524,7 +571,7 @@ mmu_init_for_kernel(void)
 
                // put standard segment descriptors in it
                segment_descriptor* virtualGDT
-                       = (segment_descriptor*)gKernelArgs.arch_args.vir_gdt;
+                       = 
(segment_descriptor*)(addr_t)gKernelArgs.arch_args.vir_gdt;
                clear_segment_descriptor(&virtualGDT[0]);
 
                // seg 0x08 - kernel 4GB code
@@ -548,7 +595,7 @@ mmu_init_for_kernel(void)
 
                // load the GDT
                gdtDescriptor.limit = GDT_LIMIT - 1;
-               gdtDescriptor.base = (void*)gKernelArgs.arch_args.vir_gdt;
+               gdtDescriptor.base = 
(void*)(addr_t)gKernelArgs.arch_args.vir_gdt;
 
                asm("lgdt       %0;"
                        : : "m" (gdtDescriptor));
diff --git a/src/system/boot/platform/bios_ia32/mmu.h 
b/src/system/boot/platform/bios_ia32/mmu.h
index fc197e9..9c59677 100644
--- a/src/system/boot/platform/bios_ia32/mmu.h
+++ b/src/system/boot/platform/bios_ia32/mmu.h
@@ -20,9 +20,15 @@ extern void mmu_init(void);
 extern void mmu_init_for_kernel(void);
 extern addr_t mmu_map_physical_memory(addr_t physicalAddress, size_t size, 
uint32 flags);
 extern void *mmu_allocate(void *virtualAddress, size_t size);
+extern void *mmu_allocate_page(addr_t *_physicalAddress);
 extern bool mmu_allocate_physical(addr_t base, size_t size);
 extern void mmu_free(void *virtualAddress, size_t size);
 
+// Used by the long mode switch code
+extern size_t mmu_get_virtual_usage();
+extern bool mmu_get_virtual_mapping(addr_t virtualAddress,
+       addr_t *_physicalAddress);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/system/boot/platform/bios_ia32/smp.cpp 
b/src/system/boot/platform/bios_ia32/smp.cpp
index 4bc2402..a7ec21b 100644
--- a/src/system/boot/platform/bios_ia32/smp.cpp
+++ b/src/system/boot/platform/bios_ia32/smp.cpp
@@ -366,7 +366,7 @@ smp_cpu_ready(void)
 
        // Set up the final idt
        idt_descr.a = IDT_LIMIT - 1;
-       idt_descr.b = (uint32 *)gKernelArgs.arch_args.vir_idt;
+       idt_descr.b = (uint32 *)(addr_t)gKernelArgs.arch_args.vir_idt;
 
        asm("lidt       %0;"
                : : "m" (idt_descr));
diff --git a/src/system/boot/platform/bios_ia32/start.cpp 
b/src/system/boot/platform/bios_ia32/start.cpp
index b15d539..717b2c2 100644
--- a/src/system/boot/platform/bios_ia32/start.cpp
+++ b/src/system/boot/platform/bios_ia32/start.cpp
@@ -22,6 +22,7 @@
 #include "hpet.h"
 #include "interrupts.h"
 #include "keyboard.h"
+#include "long.h"
 #include "mmu.h"
 #include "multiboot.h"
 #include "serial.h"
@@ -75,6 +76,12 @@ platform_boot_options(void)
 extern "C" void
 platform_start_kernel(void)
 {
+       // 64-bit kernel entry is all handled in long.cpp
+       if (gKernelArgs.kernel_image->elf_class == ELFCLASS64) {
+               long_start_kernel();
+               return;
+       }
+
        static struct kernel_args *args = &gKernelArgs;
                // something goes wrong when we pass &gKernelArgs directly
                // to the assembler inline below - might be a bug in GCC
diff --git a/src/system/boot/platform/pxe_ia32/Jamfile 
b/src/system/boot/platform/pxe_ia32/Jamfile
index fe59db7..7adb307 100644
--- a/src/system/boot/platform/pxe_ia32/Jamfile
+++ b/src/system/boot/platform/pxe_ia32/Jamfile
@@ -37,6 +37,8 @@ local bios_ia32_src =
        apm.cpp
        interrupts.cpp
        interrupts_asm.S
+       long.cpp
+       long_asm.S
 ;
 
 local bios_ia32_edid_src =
diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp 
b/src/system/kernel/arch/x86/arch_cpu.cpp
index 5ebb194..c2b5a45 100644
--- a/src/system/kernel/arch/x86/arch_cpu.cpp
+++ b/src/system/kernel/arch/x86/arch_cpu.cpp
@@ -817,7 +817,7 @@ arch_cpu_init_post_vm(kernel_args *args)
        uint32 i;
 
        // account for the segment descriptors
-       gGDT = (segment_descriptor *)args->arch_args.vir_gdt;
+       gGDT = (segment_descriptor *)(addr_t)args->arch_args.vir_gdt;
        create_area("gdt", (void **)&gGDT, B_EXACT_ADDRESS, B_PAGE_SIZE,
                B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
 
diff --git a/src/system/kernel/arch/x86/arch_int.cpp 
b/src/system/kernel/arch/x86/arch_int.cpp
index 123f575..ace0767 100644
--- a/src/system/kernel/arch/x86/arch_int.cpp
+++ b/src/system/kernel/arch/x86/arch_int.cpp
@@ -553,7 +553,7 @@ arch_int_init(struct kernel_args *args)
        interrupt_handler_function** table;
 
        // set the global sIDT variable
-       sIDTs[0] = (desc_table *)args->arch_args.vir_idt;
+       sIDTs[0] = (desc_table *)(addr_t)args->arch_args.vir_idt;
 
        // setup the standard programmable interrupt controller
        pic_init();
diff --git a/src/system/kernel/arch/x86/paging/32bit/X86PagingMethod32Bit.cpp 
b/src/system/kernel/arch/x86/paging/32bit/X86PagingMethod32Bit.cpp
index 9f84057..674c4b5 100644
--- a/src/system/kernel/arch/x86/paging/32bit/X86PagingMethod32Bit.cpp
+++ b/src/system/kernel/arch/x86/paging/32bit/X86PagingMethod32Bit.cpp
@@ -266,7 +266,7 @@ X86PagingMethod32Bit::Init(kernel_args* args,
        TRACE("X86PagingMethod32Bit::Init(): entry\n");
 
        // page hole set up in stage2
-       fPageHole = (page_table_entry*)args->arch_args.page_hole;
+       fPageHole = (page_table_entry*)(addr_t)args->arch_args.page_hole;
        // calculate where the pgdir would be
        fPageHolePageDir = (page_directory_entry*)
                (((addr_t)args->arch_args.page_hole)
@@ -276,7 +276,7 @@ X86PagingMethod32Bit::Init(kernel_args* args,
                sizeof(page_directory_entry) * NUM_USER_PGDIR_ENTS);
 
        fKernelPhysicalPageDirectory = args->arch_args.phys_pgdir;
-       fKernelVirtualPageDirectory = (page_directory_entry*)
+       fKernelVirtualPageDirectory = (page_directory_entry*)(addr_t)
                args->arch_args.vir_pgdir;
 
 #ifdef TRACE_X86_PAGING_METHOD_32_BIT
diff --git a/src/system/kernel/arch/x86/paging/pae/X86PagingMethodPAE.cpp 
b/src/system/kernel/arch/x86/paging/pae/X86PagingMethodPAE.cpp
index e7001bb..280dd14 100644
--- a/src/system/kernel/arch/x86/paging/pae/X86PagingMethodPAE.cpp
+++ b/src/system/kernel/arch/x86/paging/pae/X86PagingMethodPAE.cpp
@@ -56,7 +56,8 @@ struct X86PagingMethodPAE::ToPAESwitcher {
                fKernelArgs(args)
        {
                // page hole set up in the boot loader
-               fPageHole = (page_table_entry*)fKernelArgs->arch_args.page_hole;
+               fPageHole = (page_table_entry*)
+                       (addr_t)fKernelArgs->arch_args.page_hole;
 
                // calculate where the page dir would be
                fPageHolePageDir = (page_directory_entry*)
diff --git a/src/system/kernel/main.cpp b/src/system/kernel/main.cpp
index 6ce9648..125f284 100644
--- a/src/system/kernel/main.cpp
+++ b/src/system/kernel/main.cpp
@@ -78,6 +78,8 @@ static int32 main2(void *);
 extern "C" int
 _start(kernel_args *bootKernelArgs, int currentCPU)
 {
+       while (1) {}
+
        if (bootKernelArgs->kernel_args_size != sizeof(kernel_args)
                || bootKernelArgs->version != CURRENT_KERNEL_ARGS_VERSION) {
                // This is something we cannot handle right now - release 
kernels

############################################################################

Commit:      991e5bee90ffd98a39f012f6ce4e0740eb620073

Author:      Alex Smith <alex@xxxxxxxxxxxxxxxx>
Date:        Tue Jun 26 10:27:00 2012 UTC

Pass correct kernel_args address to the kernel.

----------------------------------------------------------------------------

diff --git a/src/system/boot/platform/bios_ia32/long.cpp 
b/src/system/boot/platform/bios_ia32/long.cpp
index 829e2ad..4ae8dc3 100644
--- a/src/system/boot/platform/bios_ia32/long.cpp
+++ b/src/system/boot/platform/bios_ia32/long.cpp
@@ -269,7 +269,7 @@ long_start_kernel()
        uint64 entry = image->elf_header.e_entry;
        uint64 stackTop = gKernelArgs.cpu_kstack[0].start
                + gKernelArgs.cpu_kstack[0].size;
-       uint64 kernelArgs = fix_address((addr_t)&gKernelArgs);
+       uint64 kernelArgs = (addr_t)&gKernelArgs;
 
        dprintf("kernel entry at 0x%llx, stack 0x%llx, args 0x%llx\n", entry,
                stackTop, kernelArgs);

############################################################################

Commit:      b8a9a3a16073d8f474ee3415e208d04f4b58b4b0

Author:      Alex Smith <alex@xxxxxxxxxxxxxxxx>
Date:        Tue Jun 26 10:42:28 2012 UTC

Copied the x86 debug console functions to x86_64.

Note that this is only temporary so that I have serial output from the kernel,
the x86 and x86_64 versions will be merged later.

----------------------------------------------------------------------------

diff --git a/src/system/kernel/arch/x86_64/arch_cpu.cpp 
b/src/system/kernel/arch/x86_64/arch_cpu.cpp
index 108b4d1..64b8571 100644
--- a/src/system/kernel/arch/x86_64/arch_cpu.cpp
+++ b/src/system/kernel/arch/x86_64/arch_cpu.cpp
@@ -30,6 +30,8 @@ arch_cpu_init_percpu(kernel_args *args, int cpu)
 status_t
 arch_cpu_init(kernel_args *args)
 {
+       dprintf("not implemented...\n");
+       while (1);
        return B_OK;
 }
 
diff --git a/src/system/kernel/arch/x86_64/arch_debug_console.cpp 
b/src/system/kernel/arch/x86_64/arch_debug_console.cpp
index cae226d..8e5db41 100644
--- a/src/system/kernel/arch/x86_64/arch_debug_console.cpp
+++ b/src/system/kernel/arch/x86_64/arch_debug_console.cpp
@@ -1,13 +1,74 @@
 /*
+ * Copyright 2002-2009, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx
+ * Copyright 2001, Rob Judd <judd@xxxxxxxxxx>
+ * Copyright 2002, Marcus Overhagen <marcus@xxxxxxxxxxxx>
  * Copyright 2012, Alex Smith, alex@xxxxxxxxxxxxxxxxx
  * Distributed under the terms of the MIT License.
+ *
+ * Copyright 2001, Travis Geiselbrecht. All rights reserved.
+ * Distributed under the terms of the NewOS License.
  */
 
 
-#include <debug.h>
+#include <KernelExport.h>
+#include <driver_settings.h>
+#include <int.h>
 
 #include <arch/cpu.h>
 #include <arch/debug_console.h>
+#include <boot/stage2.h>
+#include <debug.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+
+enum serial_register_offsets {
+       SERIAL_TRANSMIT_BUFFER          = 0,
+       SERIAL_RECEIVE_BUFFER           = 0,
+       SERIAL_DIVISOR_LATCH_LOW        = 0,
+       SERIAL_DIVISOR_LATCH_HIGH       = 1,
+       SERIAL_FIFO_CONTROL                     = 2,
+       SERIAL_LINE_CONTROL                     = 3,
+       SERIAL_MODEM_CONTROL            = 4,
+       SERIAL_LINE_STATUS                      = 5,
+       SERIAL_MODEM_STATUS                     = 6,
+};
+
+
+static const uint32 kSerialBaudRate = 115200;
+static uint16 sSerialBasePort = 0x3f8;
+       // COM1 is the default debug output port
+
+static spinlock sSerialOutputSpinlock = B_SPINLOCK_INITIALIZER;
+
+
+static void
+init_serial_port(uint16 basePort, uint32 baudRate)
+{
+       sSerialBasePort = basePort;
+
+       uint16 divisor = (uint16)(115200 / baudRate);
+
+       out8(0x80, sSerialBasePort + SERIAL_LINE_CONTROL);      /* set divisor 
latch access bit */
+       out8(divisor & 0xf, sSerialBasePort + SERIAL_DIVISOR_LATCH_LOW);
+       out8(divisor >> 8, sSerialBasePort + SERIAL_DIVISOR_LATCH_HIGH);
+       out8(3, sSerialBasePort + SERIAL_LINE_CONTROL);         /* 8N1 */
+}
+
+
+static void
+put_char(const char c)
+{
+       // wait until the transmitter empty bit is set
+       while ((in8(sSerialBasePort + SERIAL_LINE_STATUS) & 0x20) == 0)
+               asm volatile ("pause;");
+
+       out8(c, sSerialBasePort + SERIAL_TRANSMIT_BUFFER);
+}
+
+
+//     #pragma mark -
 
 
 void
@@ -43,43 +104,109 @@ arch_debug_blue_screen_getchar(void)
 int
 arch_debug_serial_try_getchar(void)
 {
-       return -1;
+       uint8 lineStatus = in8(sSerialBasePort + SERIAL_LINE_STATUS);
+       if (lineStatus == 0xff) {
+               // The "data available" bit is set, but also all error bits. 
Likely we
+               // don't have a valid I/O port.
+               return -1;
+       }
+
+       if ((lineStatus & 0x1) == 0)
+               return -1;
+
+       return in8(sSerialBasePort + SERIAL_RECEIVE_BUFFER);
 }
 
 
 char
 arch_debug_serial_getchar(void)
 {
-       while(true)
+       while (true) {
+               uint8 lineStatus = in8(sSerialBasePort + SERIAL_LINE_STATUS);
+               if (lineStatus == 0xff) {
+                       // The "data available" bit is set, but also all error 
bits. Likely
+                       // we don't have a valid I/O port.
+                       return 0;
+               }
+
+               if ((lineStatus & 0x1) != 0)
+                       break;
+
                PAUSE();
-       return 0;
+       }
+
+       return in8(sSerialBasePort + SERIAL_RECEIVE_BUFFER);
 }
 
 
+static void
+_arch_debug_serial_putchar(const char c)
+{
+       if (c == '\n') {
+               put_char('\r');
+               put_char('\n');
+       } else if (c != '\r')
+               put_char(c);
+}
+
 void
 arch_debug_serial_putchar(const char c)
 {
-
+       cpu_status state = 0;
+       if (!debug_debugger_running()) {
+               state = disable_interrupts();
+               acquire_spinlock(&sSerialOutputSpinlock);
+       }
+
+       _arch_debug_serial_putchar(c);
+
+       if (!debug_debugger_running()) {
+               release_spinlock(&sSerialOutputSpinlock);
+               restore_interrupts(state);
+       }
 }
 
 
 void
 arch_debug_serial_puts(const char *s)
 {
-
+       cpu_status state = 0;
+       if (!debug_debugger_running()) {
+               state = disable_interrupts();
+               acquire_spinlock(&sSerialOutputSpinlock);
+       }
+
+       while (*s != '\0') {
+               _arch_debug_serial_putchar(*s);
+               s++;
+       }
+
+       if (!debug_debugger_running()) {
+               release_spinlock(&sSerialOutputSpinlock);
+               restore_interrupts(state);
+       }
 }
 
 
 void
 arch_debug_serial_early_boot_message(const char *string)
 {
-
+       // this function will only be called in fatal situations
+       // ToDo: also enable output via text console?!
+       arch_debug_console_init(NULL);
+       arch_debug_serial_puts(string);
 }
 
 
 status_t
 arch_debug_console_init(kernel_args *args)
 {
+       // only use the port if we could find one, else use the standard port
+       if (args != NULL && args->platform_args.serial_base_ports[0] != 0)
+               sSerialBasePort = args->platform_args.serial_base_ports[0];
+
+       init_serial_port(sSerialBasePort, kSerialBaudRate);
+
        return B_OK;
 }
 
diff --git a/src/system/kernel/main.cpp b/src/system/kernel/main.cpp
index 125f284..6ce9648 100644
--- a/src/system/kernel/main.cpp
+++ b/src/system/kernel/main.cpp
@@ -78,8 +78,6 @@ static int32 main2(void *);
 extern "C" int
 _start(kernel_args *bootKernelArgs, int currentCPU)
 {
-       while (1) {}
-
        if (bootKernelArgs->kernel_args_size != sizeof(kernel_args)
                || bootKernelArgs->version != CURRENT_KERNEL_ARGS_VERSION) {
                // This is something we cannot handle right now - release 
kernels


Other related posts: