Operation map
How Popcorn boots and runs in the v0.6 tree: GRUB Multiboot2 loads the ELF, start builds an identity map and enters long mode, kmain runs init_boot_screen (PMM/VMM bring-up via memory_init, timer, scheduler), then init_transition_to_console enables keyboard IRQs, re-enables the PIT toward scheduler_tick, and enters the shell loop that dequeues scancodes (not port polling).
Interactive hierarchy
Hierarchical map
Expand branches (▸). Each node updates the inspector.
Loading…
Flow diagrams
Interrupt delivery
flowchart TD PIT[PIT IRQ0] --> PIC1[PIC master] KB[Keyboard IRQ1] --> PIC1 PIC1 --> CPU[CPU interrupt] CPU --> IDT[IDT dispatch] IDT --> T0[timer_handler asm] IDT --> K0[keyboard_handler asm] IDT --> S0[syscall_handler_asm] T0 --> T1[timer_interrupt_handler C] T1 --> TH["tick_handler: scheduler_tick"] K0 --> K1[keyboard_handler_main C] K1 --> Q[key_queue push] Q --> SH2[kmain / Dolphin dequeue] S0 --> SD[syscall_dispatch C]
Lifecycle — host to shell
flowchart TB
subgraph Host["Host (build and QEMU)"]
ISO[GRUB ISO] --> QEMU[QEMU -cdrom]
end
subgraph Guest["Guest (Popcorn kernel)"]
QEMU --> ENTRY["start: kernel.asm"]
ENTRY --> KM[kmain]
KM --> INIT[init_boot_screen]
INIT --> MEM[memory_init]
INIT --> TIM[timer_init]
INIT --> SCH[scheduler_init]
INIT --> SYS[syscall_init]
INIT --> POP[register_pop modules]
INIT --> GO[init_transition_to_console]
GO --> MB[multiboot2_parse]
GO --> IDT[idt_init + PIC]
GO --> KB[kb_init]
GO --> TE["timer_enable + tick to scheduler_tick"]
GO --> SH[Shell: dequeue + HLT loop]
IRQ0[PIT IRQ0] --> TICK[timer_interrupt_handler]
TICK --> ST[scheduler_tick guarded]
IRQ1[KB IRQ1] --> KH[keyboard_handler_main → queue]
INT80[int 0x80] --> SC[syscall_dispatch]
SH --> EX[execute_command]
end
Host --> Guest
Reference sections
0 · Repository layout
Popcorn/ ├── src/ │ ├── link.ld │ ├── core/ │ ├── pops/ │ ├── includes/ │ └── build/linux.sh · macos.sh · popcorn_build/ (host)
Only the linked ELF runs inside QEMU; Python and shell helpers are host tooling.
1 · Boot chain (GRUB → start → kmain)
GRUB (guest)
└─ multiboot2 /boot/kernel
└─ loads ELF to link address
└─ jumps to symbol `start` in core/kernel.asm
start saves the Multiboot2 info pointer, builds a 1 GiB identity map (2 MiB huge pages), enables long mode, sets rsp, calls kmain. ASM exports connect IRQ, exceptions, and syscall gates to C.
4 · init_boot_screen + transition
init_boot_screen console_init → header → memory_init → timer_init → scheduler_init → syscall_init → register_pop_module ×9 → progress → wait Enter → init_transition_to_console init_transition_to_console multiboot2_parse → idt_init (PIC, masks, load_idt/sti) → kb_init → timer_set_tick_handler(scheduler_tick) → timer_enable → prompt + status bar
Boot screen already runs memory_init (PMM + VMM), timer_init, scheduler_init (records kernel PML4). Console transition enables IRQ1 then PIT. Pop order: spinner, uptime, filesystem, sysinfo, memory, cpu, dolphin, halt, shimjapii.
8 · Syscall surface (representative)
exit, read, write, open, close, seek, getpid, fork, exec, wait, malloc, free, mmap, munmap, gettime, sleep, yield, getcwd, chdir, stat, ioctl
syscall_dispatch uses the convention in ctx->rax; IDT vector 0x80 is installed as a user-accessible interrupt gate in idt_init.
13 · Reading map
| Concern | Primary files |
|---|---|
| Entry, long mode, ISR stubs | core/kernel.asm |
| Link address, sections | link.ld |
| Boot UI + ordered init | core/init.c |
| Shell + IDT/PIC + key queue | core/kernel.c, includes/keyboard_queue.h |
| VMM / page tables | core/vmm.c, includes/vmm.h |
| PMM + heap pools | core/memory.c |
| Timer IRQ | core/timer.c + asm stub |
| Scheduler + CR3 switch | core/scheduler.c + context_switch.asm |
| Syscalls | core/syscall.c + asm stub |
| Multiboot | core/multiboot2.c, includes/multiboot2.h |
| Pop registry | core/pop_module.c, includes/pop_module.h |
| Individual pops | pops/*.c |
14 · Caveats
Educational kernel: syscall gate exists; per-task PML4 is wired, but full user isolation is still evolving.
0.6: shell waits on the IRQ key queue with HLT; keep cli windows in context switch short to avoid input latency spikes.
Scheduler skips the first PIT tick and refuses switch while bootstrap_on_kmain_stack() is true.
execute_all_pops is a batch helper; some commands invoke pops directly.