Skip to content

Kernel Entry Point

opencode-agent[bot] edited this page May 10, 2026 · 1 revision

Kernel Entry Point

The assembly-to-Java transition point where GRUB loads the kernel and jumps to Java's Main.vmMain().

Overview

The kernel entry point is the critical bridge between the native x86 assembly bootstrap and the Java runtime initialization. This transition occurs in two stages:

  1. Assembly entry: GRUB loads the Multiboot ELF image and jumps to sys_start in kernel.asm
  2. Java entry: After full assembly initialization, control transfers to Main.vmMain() in org.jnode.boot

This is Value 5 in the JNode documentation system — a critical core VM initialization bridge.

Key Components

Component File Description
sys_start core/src/native/x86/kernel.asm:17 Global entry point recognized by GRUB
real_start core/src/native/x86/kernel.asm:36 Main initialization routine
Main.vmMain() core/src/core/org/jnode/boot/Main.java:61 First Java method executed
VmSystem core/src/core/org/jnode/vm/VmSystem.java VM initialization coordinator
InitJarProcessor core/src/core/org/jnode/boot/InitJarProcessor.java Extracts plugins from init-jar
BootImageBuilder builder/src/builder/org/jnode/build/x86/BootImageBuilder.java Builds boot image at compile time

How It Works

Stage 1: GRUB to Assembly Entry

When GRUB loads the JNode boot image, it performs a Multiboot-compliant jump:

GRUB loads ELF → jumps to sys_start (EAX=0x2BADB002, EBX=multiboot_info)

The Multiboot header in kernel.asm (lines 20-34) declares:

  • Magic: 0x1BADB002
  • Features: 0x00010007
  • Entry address: real_start

Stage 2: Assembly Initialization (real_start)

The real_start routine performs these critical steps:

real_start:
    mov esp, Lkernel_esp        ; Set up kernel stack
    cld                          ; Clear direction flag
    cmp eax, 0x2BADB002          ; Verify Multiboot magic
    je multiboot_ok              ; Continue if valid
    
; Initialize subsystems:
; 1. Copy Multiboot info block (lines 46-51)
; 2. Memory detection (line 62-64)
; 3. Memory map parsing (lines 67-89)
; 4. VBE info copy (lines 100-113)
; 5. Init-jar location (lines 117-138)
; 6. A20 line check (lines 143-149)
; 7. Kernel debugger (line 152)
; 8. CPU feature detection (line 163)
; 9. Memory manager (lines 167-174)
; 10. IDT setup (line 176)
; 11. FPU/SSE initialization (lines 180-183)

Stage 3: Transition to Userspace

At lines 187-206, the assembly performs a critical transition to userspace to call Java:

; Go into userspace
mov ABX, Luser_esp
mov ACX, go_user_cs
mov ASI, USER_DS
mov ADI, USER_CS
push ASI           ; old SS
push ABX           ; old ESP
pushf              ; old EFLAGS
push ADI           ; old CS
push ACX           ; old EIP
pushf
pop AAX
and eax, ~F_NT     ; Clear nested task flag
push AAX
popf
iret               ; Switch to Java entry point

Stage 4: Java Entry Point

The iret instruction transfers control to Main.vmMain():

@LoadStatics
@Uninterruptible
public static int vmMain() {
    Unsafe.debug("Starting JNode\n");
    final long start = VmSystem.currentKernelMillis();

    Unsafe.debug("VmSystem.initialize\n");
    VmSystem.initialize();
    
    // Load plugins from initjar
    BootLogInstance.get().info("Loading initjar plugins");
    final InitJarProcessor proc = new InitJarProcessor(VmSystem.getInitJar());
    List<PluginDescriptor> descriptors = proc.loadPlugins(pluginRegistry);

    BootLogInstance.get().info("Starting PluginManager");
    final PluginManager piMgr = new DefaultPluginManager(pluginRegistry);
    piMgr.startSystemPlugins(descriptors);

    // Launch main class
    final Class<?> mainClass = loader.loadClass(mainClassName);
    mainMethod.invoke(null, new Object[]{proc.getMainClassArguments()});
}

Init-Jar Processing

The init-jar is a nested archive inside the boot image containing all plugin JARs and descriptors. At boot:

  1. Location: InitJarProcessor receives the init-jar memory range from VmSystem.getInitJar()
  2. Extraction: InitJarPluginLoader iterates through the JAR entries
  3. Registration: Each plugin descriptor is added to the PluginRegistry
  4. Startup: DefaultPluginManager.startSystemPlugins() starts plugins in dependency order

Boot Image Builder Integration

BootImageBuilder (builder/src/builder/org/jnode/build/x86/BootImageBuilder.java) plays a critical role:

  1. Pre-compiles all Java classes for the boot image
  2. Patches the kernel entry address into the Multiboot header
  3. Embeds the init-jar containing all plugin JARs
  4. Sets up the pluginRegistry static field that Main.vmMain() uses

The pluginRegistry field is initialized in BootImageBuilder.initMain() (line 50 of Main.java references this).

Gotchas

  1. Multiboot magic validation: If EAX != 0x2BADB002, the kernel jumps to no_multiboot_loader and halts
  2. A20 line check: Lines 143-149 loop forever if A20 is not enabled — a common BIOS issue
  3. Init-jar empty: If no boot modules are provided, initJar_start == initJar_end and no plugins load
  4. Static initialization: The @LoadStatics annotation on vmMain() ensures statics are initialized at runtime, not build time
  5. @Uninterruptible requirement: vmMain() must not trigger GC safepoints during critical VM setup

Related Pages

Related Concepts

  • Multiboot — Boot protocol used by GRUB
  • Init-jar — Nested archive with plugin JARs
  • Boot image — The compiled ELF binary loaded by GRUB
  • VmSystem — Main VM initialization class
  • @LoadStatics — Runtime static initialization annotation

Clone this wiki locally