armkernelarm64armv8

What is SP0 and SPn in AArch64?


If the exception is being taken at the same Exception level, the stack pointer to be used (SP0 or SPn)

In a document of AArch64 exception vector table, an entry is selected based off the factor above. I couldn't find any useful information regarding SP0 and SPn, so I'd like to ask why there are two stack pointers and what's the difference between them? A link is also appreciated!


Solution

  • Disclaimer: I am not an expert on the Armv8-a architecture, I have just been writing some bare-metal code dealing with exceptions on a Cortex-A53 for the purpose of learning.

    The document you are pointing to explains, although succinctly, that:

    From the Arm documentation for the SPSel system register:

    Bits [63:1] Reserved, RES0.
    SP, bit [0] Stack pointer to use. Possible values of this bit are:
    
    0b0 Use SP_EL0 at all Exception levels.
    0b1 Use SP_ELx for Exception level ELx.
    
    The reset behaviour of this field is: On a Warm reset, this field resets to 1. 
    

    Using the stack pointer dedicated to a given exception level helps isolating more the code executing at, say, EL3, from the less-privileged code executing at EL2..EL0, since different memory areas can be used for implementing the stack for each exception level.

    If you are writing your own bare-metal code, the value to set in SPSel would ultimately be your choice: For example, when using a standard Arm-Trusted firmware (code running at EL3)/u-boot (code running at EL2) bundle on an Alwinner H6 Cortex-A53:

    SPSel.s:

            .global _start
        .align 3
            .text
    _start:
            mrs x0, SPSel
            ret
    

    Building:

    /opt/arm/11/gcc-arm-11.2-2022.02-x86_64-aarch64-none-elf/bin/aarch64-none-elf-gcc -nostartfiles -nostdlib --freestanding  -Wl,--section-start=.text=0x40080000 -o SPSel.elf SPSel.s
    /opt/arm/11/gcc-arm-11.2-2022.02-x86_64-aarch64-none-elf/bin/aarch64-none-elf-objcopy -O srec SPSel.elf SPSel.srec
    /opt/arm/11/gcc-arm-11.2-2022.02-x86_64-aarch64-none-elf/bin/aarch64-none-elf-objdump -D -j .text SPSel.elf > SPSel.lst
    

    Executing:

    => loads
    ## Ready for S-Record download ...
    
    ## First Load Addr = 0x40080000
    ## Last  Load Addr = 0x40080007
    ## Total Size      = 0x00000008 = 8 Bytes
    ## Start Addr      = 0x40080000
    => go 0x40080000
    ## Starting application at 0x40080000 ...
    ## Application terminated, rc = 0x0
    =>
    

    The value of SPSel returned in x0 is 0, i.e. the SP bit of SPSelis 0, and SP_EL0 is therefore the stack-pointer register that will be used at all EL3..EL0 exception levels.