QCPU
  • Instruction set
  • CSRs
  • Assembly
  • Guide
  • Snippets

On this page

  • 1 Setting up a stack
  • 2 Kernel space
  • 3 Kernel logical space
  • 4 Page mapping

Boot process

memory
control-flow
A CPU’s first steps and different execution modes.
Published

October 12, 2025

On reset, all QCPU features (e.g. prot, virtual memory) are disabled and the microprocessor jumps to the 0x0800 entrypoint in physical memory. For any direct application or kernel, the first step to perform is to set up a stack pointer and enable kernel logical mapping.

                 64 KiB
                (16 bit)
0x0000                   0xC000   0xFFFF
   |------------------------|--------|
   | userland               | kernel |
     48 KiB                   16 KiB

QCPU has a single virtual address space, divided into multiple regions. For hardware simplicity, the kernel-protected region from 0xC000 is fixed.

1 Setting up a stack

A stack is configured by setting the sp register. It grows downwards, as memory operations take a static unsigned immediate as offset, so the stack pointer is set to the last element in the region.

@section stack
@align 256
@region 512
@define stlen, 512
@define stbase, .sttop + @slen

.sttop:           reserve u8, @stlen      ; top of stack

@end

@section root
@align 2

_:                lui sp, @stbase
                  bkpt

For allocating to the stack, use the alloc pseudo-instruction:

                  alloc -4                ; 4 bytes
                  mstw x1, sp, 0          ; sp+0 sp+1 = x1
                  mstw x2, sp, 2          ; sp+2 sp+3 = x2

2 Kernel space

Kernel space is divided into two parts: logical space, and virtually-mapped space:

                      16 KiB
          0xC000      0xF000      0xFFFF
             |-----------|-----------|
 | userland  | kfixed    | kvariable |
               12 KiB      4 KiB

Kernel text and global data is put in the logical kfixed space. Note how there exists two virtually-mapped regions in the virtual memory address space: userland and kernel-protected virtual memory. These regions are configured independently through the CSRs.

For architectural simplicity, address 0xC000 is the fixed watermark of the kernel. Any pages above the watermark are kernel-protected when in kernel-protected mode (enabled in the ft CSR).

System calls, and any other hardware interrupt, put the CPU into kernel mode and jump to designated parts of kernel space (configured in the vec CSR). If any other operation in userland tries to access kernel space, a page fault is triggered. Jumping out of kernel space exits kernel mode. Memory accesses from within kernel mode are allowed anywhere, given that a page mapping exists.

3 Kernel logical space

Kernel logical space is one of two virtual memory mapping types. When the kernel-protection bit is set in the ft CSR, virtual region 0xC000 - 0xFFFF is mapped to its equivalent starting from 0x0000 in physical memory.

@section root
@align 2

// executed in 0x0800 physical memory

_:                lli x1, 0b00000001            ; enable bit for kp/kernel-protect
                  csrw x1, 0x043                ; write features
                  ftlb                          ; TLB flush on next jump
                  jmp .kmain                    ; absolute jump to virtual memory addr

// executed in 0xC8XX logical memory

@align 32

.kmain:           bkpt

// linked as virtual memory, so don't try to use labels in the time
// we're in physical memory, except when jumping to the virtual-translated
// entrypoint after flush

@linkinfo(origin) root, 0xC800

With kernel protection/logical mapping disabled, the CPU is in kernel mode, and therefore doesn’t trigger a page fault going into the now kernel-protected space.

4 Page mapping

Page mapping translates virtual pages to physical pages through the kernel’s page table. There are two page table CSRs available: pmat and pmatk (physical memory address translation user/kernel, respectively). They hold the address to the separate page tables.

Cleverly, having two page tables allows the kernel to switch userland by updating the pmat CSR only, keeping kernel mappings intact.

                 64 KiB
 {           }---------\/{           }
 |-----------|---------MM|-----------|
 | userland  | kfixed    | kvariable |
   48 KiB      12 KiB      4 KiB