ARM64-A Porting Guide

Overview

XWOS source code already includes most of the ARM64-Cortex-A architecture code:

  • Architecture Description Layer (ADL)
    • ARMv8a: XWOS/xwcd/soc/arm/v8a
  • CPU Description Layer (CDL)
    • m0: XWOS/xwcd/soc/arm/v8a/a72
    • m0p: XWOS/xwcd/soc/arm/v8a/a76a55
  • SoC Description Layer (SDL)
    • UNISOC A7870: XWOS/xwcd/soc/arm/v8a/a76a55/a7870
    • Raspberry Pi 4B SoC: XWOS/xwcd/soc/arm/v8a/a72/bcm2711

For a new SoC chip, you only need to add an SoC folder in the CPU folder, which includes:

  • Initialization: soc_init.h and soc_init.c
  • Interrupts: xwosimpl_irq.h and xwosimpl_irq.c
    • Must provide implementations for functions declared in the XWOS Kernel Porting Layer (XWOSPL) XWOS/xwos/ospl/irq.h.
  • Scheduler: xwosimpl_skd.h and xwosimpl_skd.c
    • Must provide implementations for functions declared in the XWOS Kernel Porting Layer (XWOSPL) XWOS/xwos/ospl/skd.h.
  • Tick Timer: xwosimpl_syshwt.h and xwosimpl_syshwt.c
    • Must provide implementations for functions declared in the XWOS Kernel Porting Layer (XWOSPL) XWOS/xwos/ospl/syshwt.h.
  • .lds: Linker script

Type Definitions

The XWOS Kernel Porting Layer (XWOSPL) XWOS/xwos/ospl/type.h requires the SoC to provide definitions of standard types:

XWOS/xwcd/soc/arm/v8a/xwosimpl_arch_type.h

Compiler Macro Definitions

The XWOS Porting Implementation Layer is located at:

XWOS/xwcd/soc/arm/v8a/xwosimpl_arch_compiler.h
  • gcc: XWOS/xwcd/soc/arm/v8a/compiler/gcc.h
  • llvm: XWOS/xwcd/soc/arm/v8a/compiler/llvm.h

Lock-Free Queue Implementation

The XWOS Porting Implementation Layer is located at:

XWOS/xwcd/soc/arm/v8a/xwosimpl_arch_lfq.h
XWOS/xwcd/soc/arm/v8a/xwosimpl_arch_lfq.c

Spinlock

The XWOS Porting Implementation Layer is located at:

XWOS/xwcd/soc/arm/v8a/xwosimpl_arch_spinlock.h

Architecture Instructions

The XWOS Porting Implementation Layer is located at:

XWOS/xwcd/soc/arm/v8a/xwosimpl_arch_isa.h

Bit Operations

The XWOS Porting Implementation Layer is located at:

XWOS/xwcd/soc/arm/v8a/xwosimpl_arch_xwbop.c

8-bit Atomic Operations

The XWOS Kernel Porting Layer (XWOSPL) XWOS/xwos/ospl/xwaop8.h requires the SoC to provide single-byte atomic operation implementations at the assembly instruction level:

XWOS/xwcd/soc/arm/v8a/xwaop/s8.c
XWOS/xwcd/soc/arm/v8a/xwaop/u8.c

16-bit Atomic Operations

The XWOS Kernel Porting Layer (XWOSPL) XWOS/xwos/ospl/xwaop16.h requires the SoC to provide double-byte atomic operation implementations at the assembly instruction level:

XWOS/xwcd/soc/arm/v8a/xwaop/s16.c
XWOS/xwcd/soc/arm/v8a/xwaop/u16.c

32-bit Atomic Operations

The XWOS Kernel Porting Layer (XWOSPL) XWOS/xwos/ospl/xwaop32.h requires the SoC to provide 4-byte atomic operation implementations at the assembly instruction level:

XWOS/xwcd/soc/arm/v8a/xwaop/s32.c
XWOS/xwcd/soc/arm/v8a/xwaop/u32.c

64-bit Atomic Operations

The XWOS Kernel Porting Layer (XWOSPL) XWOS/xwos/ospl/xwaop64.h requires the SoC to provide 8-byte atomic operation implementations at the assembly instruction level:

XWOS/xwcd/soc/arm/v8a/xwaop/s64.c
XWOS/xwcd/soc/arm/v8a/xwaop/u64.c

System Initialization

  • SPSel set to 1: Different EL levels use different SP registers

  • SCTLR_EL1.EE = 0: Select little-endian format

  • SCTLR_EL1.SA = 1: Enable stack alignment check

  • SCTLR_EL1.A = 0: Disable alignment check, as alignment checks often cause sync exceptions

  • SCTLR_EL1.C = 1: Enable data cache

  • SCTLR_EL1.I = 1: Enable instruction cache

  • SCTLR_EL2.EE = 0: Select little-endian format

  • SCTLR_EL2.SA = 1: Enable stack alignment check

  • SCTLR_EL2.A = 0: Disable alignment check, as alignment checks often cause sync exceptions

  • SCTLR_EL2.C = 1: Enable data cache

  • SCTLR_EL2.I = 1: Enable instruction cache

  • CPACR_EL1.FPEN = 0b11: Enable floating-point unit

  • Virtualization is temporarily not enabled

HCR_EL2.VM = 0 HCR_EL2.TGE = 0

Interrupts

The XWOS Porting Implementation Layer is located at:

XWOS/xwcd/soc/arm/v8a/[CPU]/[SoC]/xwosimpl_irq.h
XWOS/xwcd/soc/arm/v8a/[CPU]/[SoC]/xwosimpl_irq.c
  • Exceptions are not handled in EL3

SCR_EL3.FIQ = 0 SCR_EL3.IRQ = 0 HCR_EL3.EA = 0 HCR_EL3.HCE = 1: Enable HVC instruction

  • Disable traps in CPTR_EL3

  • Disable traps in CPTR_EL2

  • Handle interrupts in EL2

HCR_EL2.AMO = 1 HCR_EL2.IMO = 1 HCR_EL2.FMO = 1

Scheduler

The XWOS Kernel Porting Layer (XWOSPL) XWOS/xwos/ospl/skd.h requires the SoC to provide implementations for scheduler context switching and other operations:

XWOS/xwcd/soc/arm/v8a/[CPU]/[SoC]/xwosimpl_skd.h
XWOS/xwcd/soc/arm/v8a/[CPU]/[SoC]/xwosimpl_skd.c

The specific implementation methods for SoCs based on the ARM-V8A architecture are essentially the same. Therefore, they can be uniformly implemented as:

XWOS/xwcd/soc/arm/v8a/arch_skd.h
XWOS/xwcd/soc/arm/v8a/arch_skd.c

The XWOS kernel runs at EL2, using sp_el2

Thread

Threads run at EL2T, the kernel runs at EL2H.

Stack

  • According to AAPCS64 requirements, a 16-byte aligned full descending stack is used, therefore in the configuration file cfg/xwos.h:
    • XWMMCFG_FD_STACK is configured as 1
    • XWMMCFG_ALIGNMENT is configured as 16U

Stack Layout


            +------------+-----------------------------+
   sp+0x31c | reserved   |                             |
   sp+0x318 | reserved   |                             |
   sp+0x314 | FPCR       |                             |
   sp+0x310 | FPSR       |   volatile (caller-saved)   |
            +------------+-----------------------------+
   sp+0x300 | q31        |   volatile (caller-saved)   |
   sp+0x2F0 | q30        |   volatile (caller-saved)   |
   sp+0x2E0 | q29        |   volatile (caller-saved)   |
   sp+0x2D0 | q28        |   volatile (caller-saved)   |
   sp+0x2C0 | q27        |   volatile (caller-saved)   |
   sp+0x2B0 | q26        |   volatile (caller-saved)   |
   sp+0x2A0 | q25        |   volatile (caller-saved)   |
   sp+0x290 | q24        |   volatile (caller-saved)   |
   sp+0x280 | q23        |   volatile (caller-saved)   |
   sp+0x270 | q22        |   volatile (caller-saved)   |
   sp+0x260 | q21        |   volatile (caller-saved)   |
   sp+0x250 | q20        |   volatile (caller-saved)   |
   sp+0x240 | q19        |   volatile (caller-saved)   |
   sp+0x230 | q18        |   volatile (caller-saved)   |
   sp+0x220 | q17        |   volatile (caller-saved)   |
   sp+0x210 | q16        |   volatile (caller-saved)   |
            +------------+-----------------------------+
   sp+0x200 | q15        | non-volatile (callee-saved) |
   sp+0x1F0 | q14        | non-volatile (callee-saved) |
   sp+0x1E0 | q13        | non-volatile (callee-saved) |
   sp+0x1D0 | q12        | non-volatile (callee-saved) |
   sp+0x1C0 | q11        | non-volatile (callee-saved) |
   sp+0x1B0 | q10        | non-volatile (callee-saved) |
   sp+0x1A0 | q9         | non-volatile (callee-saved) |
   sp+0x190 | q8         | non-volatile (callee-saved) |
            +------------+-----------------------------+
   sp+0x180 | q7         |   volatile (caller-saved)   |
   sp+0x170 | q6         |   volatile (caller-saved)   |
   sp+0x160 | q5         |   volatile (caller-saved)   |
   sp+0x150 | q4         |   volatile (caller-saved)   |
   sp+0x140 | q3         |   volatile (caller-saved)   |
   sp+0x130 | q2         |   volatile (caller-saved)   |
   sp+0x120 | q1         |   volatile (caller-saved)   |
   sp+0x110 | q0         |   volatile (caller-saved)   |
            +------------+-----------------------------+
   sp+0x108 | spsr       |   volatile (caller-saved)   |
   sp+0x100 | pc(elr)    |   volatile (caller-saved)   |
   sp+0xF8  | sp         |   volatile (caller-saved)   |
   sp+0xF0  | lr         |   volatile (caller-saved)   |
   ---------+------------+-----------------------------+
   sp+0xE8  | x29        | non-volatile (callee-saved) |
   sp+0xE0  | x28        | non-volatile (callee-saved) |
   sp+0xD8  | x27        | non-volatile (callee-saved) |
   sp+0xD0  | x26        | non-volatile (callee-saved) |
   sp+0xC8  | x25        | non-volatile (callee-saved) |
   sp+0xC0  | x24        | non-volatile (callee-saved) |
   sp+0xB8  | x23        | non-volatile (callee-saved) |
   sp+0xB0  | x22        | non-volatile (callee-saved) |
   sp+0xA8  | x21        | non-volatile (callee-saved) |
   sp+0xA0  | x20        | non-volatile (callee-saved) |
   sp+0x98  | x19        | non-volatile (callee-saved) |
   sp+0x90  | x18        | non-volatile (callee-saved) |
   ---------+------------+-----------------------------+
   sp+0x88  | x17        |   volatile (caller-saved)   |
   sp+0x80  | x16        |   volatile (caller-saved)   |
   sp+0x78  | x15        |   volatile (caller-saved)   |
   sp+0x70  | x14        |   volatile (caller-saved)   |
   sp+0x68  | x13        |   volatile (caller-saved)   |
   sp+0x60  | x12        |   volatile (caller-saved)   |
   sp+0x58  | x11        |   volatile (caller-saved)   |
   sp+0x50  | x10        |   volatile (caller-saved)   |
   sp+0x48  | x9         |   volatile (caller-saved)   |
   sp+0x40  | x8         |   volatile (caller-saved)   |
   sp+0x38  | x7         |   volatile (caller-saved)   |
   sp+0x30  | x6         |   volatile (caller-saved)   |
   sp+0x28  | x5         |   volatile (caller-saved)   |
   sp+0x20  | x4         |   volatile (caller-saved)   |
   sp+0x18  | x3         |   volatile (caller-saved)   |
   sp+0x10  | x2         |   volatile (caller-saved)   |
   sp+0x08  | x1         |   volatile (caller-saved)   |
   sp+0x00  | x0         |   volatile (caller-saved)   |
            --------------------------------------------
  • Note: According to the official manual, the x18 register should be caller-saved, but the Linux kernel uses this register as the ShadowCallStack pointer (when configuration CONFIG_SHADOW_CALL_STACK is y), in which case x18 should be callee-saved.
  • XWOS follows Linux’s convention, so x18 is also callee-saved.
  • The compilation option -ffixed-x18 needs to be added.

Note: The current version of XWOS has not yet implemented saving and restoring of floating-point context. It plans to be implemented based on Lazy Save and Restore technology:

  • SIMD registers (q0~q31)
  • ARMv8.2-A introduced SVE, q0q31 extended to z0z31, variable-length registers, up to 2048 bits
  • ARMv9-A introduced SVE2, adding 16 predicate registers (P0-P15)
  • ARMv9-A introduced SME, adding the ZA register, up to 64KiB

Tick Timer

The XWOS Kernel Porting Layer (XWOSPL) XWOS/xwos/ospl/syshwt.h requires the SoC to provide an implementation of the tick timer:

xwcd/soc/arm/v8a/[CPU]/[SoC]/xwosimpl_soc_syshwt.h
xwcd/soc/arm/v8a/[CPU]/[SoC]/xwosimpl_soc_syshwt.c

XWOS runs at EL2, using cnthp:

xwcd/soc/arm/v8a/arch_timer.h
xwcd/soc/arm/v8a/arch_timer.c