assemblyarminstruction-set

How does arm svc instruction works?


How does SVC (SWI) instruction works? Where it puts supevisor call id and other data? Where to get a list of all supervisor call ids, its parameters and return types?

Im tried to find that all in google but it shows only useless things and nothing about supervisor calls. Documentations also have too small amount of need data


Solution

  • I'll describe AArch64 here, but AArch32 is similar. I'll also take a typical example where the svc is invoked at EL0 ("user mode") and handled at EL1 ("kernel mode"). The authoritative reference for everything below is the Armv8-A Architecture Reference Manual (ARM), version I.a.

    Unlike the x86 int instruction, the immediate operand to svc has no role in determining the vector to the exception handler. Instead, the vector is always obtained by taking the vector base address from the system register VBAR_EL1 and adding an offset determined by the type of exception and the exception level. See Table R_RYXCL in the ARM. In this case, since svc is a synchronous exception coming from a lower exception level using AArch64, the offset is 0x400.

    Exception handling on ARM includes storing a "syndrome" code into ESR_EL1, and in the case of svc, the immediate operand is stored as the low 16 bits of the syndrome. See the description of svc at C6.2.365. The CPU itself doesn't do anything further with the operand value. So it is up to the operating system designer to determine how (or if) to use this value. Thus you have to consult the documentation for your operating system to see what, if anything, it does. Information on the calling conventions, register contents, return values, etc, would also be up to the OS to specify as part of its ABI, though most use some variation of the AArch64 Procedure Call Standard.

    An OS ABI could be designed such that it uses this value to specify what service is to be performed. However, many OSes don't do this, and have the program specify the service with a system call number in one of the general-purpose registers instead. This is what Linux does; it expects the system call number to be passed in x8, and the immediate operand to svc is simply ignored. A table of the meaning of the different system call numbers for Linux, and the parameters they expect, can be found at https://chromium.googlesource.com/chromiumos/docs/+/HEAD/constants/syscalls.md#arm64-64_bit. The actual behavior of each named system call (write, open, etc) is found in its man page.