ARM Banked register - arm

In ARM there is a concept of Banked Register. While reading many questions and their answer and various other resources about what is Banked mean here. Then I got this definition:
Register banking refers to providing multiple copies of a register at the same address. Not all registers can be seen at once.
But my query here is that How multiple copies of registers are created. Because we have single register file in our core. And if there is another mode then it will get the new copy of the banked register that will not contain any data and not going to access the data of another mode register.
Then how this copy of register is created?

Register banking refers to providing multiple copies of a register at the same address. Not all registers can be seen at once.
This is some what correct. However, the register does not have a 'traditional address'. The majority of the arm instructions or 'binary encodings' have register as source or destination arguments. There are sixteen base register so four bits are needed for each register in a binary instruction. A typical instruction takes 12 bits (out of 32bits) to describe the three registers (two source and one destination). These bits in the instruction are the 'address' in the definition above.
But my query here is that How multiple copies of registers are created. Because we have single register file in our core. And if there is another mode then it will get the new copy of the banked register that will not contain any data and not going to access the data of another mode register. Then how this copy of register is created?
They are not 'created' dynamically. The banked registers are part of the 'register file' of the core and always exist. The issue is that the typical instructions can not access some banked registers unless a 'mode switch' occurs. This maybe from user to IRQ mode or from normal to secure world with trustzone.
So running the same code in different modes may end up accessing different (banked) registers. In this way, user code never affects the IRQ stack and vice-versa. Perhaps more importantly, the IRQ code could corrupt non-banked user registers if careful context saving is not performed at the start and end of an IRQ.
See: Accessing banked registers on ARM for information on how you might access these different registers.
The newer ARMv7 instruction mrs r2,sp_svc breaks this banked register rule and allows access to the banked registers directly without switching a mode. the intent is to allow context switching code to easily access the banked registers for saving and restoring without a mode switch.
The traditional instruction ldm rN, {sp,lr}^ allows saving of user stack pointer and link register without switching modes. Again, this has a special encoding (or addressing as per your definition).
Banking is also done with CP15 system registers in trustzone. TrustZone monitor mode and banked IFSR... maybe interesting for anyone looking at that ARM 'banking' which is conceptually the same as the register banking.

I count 31 registers needed to support the traditional arm. Several r13s and r14s a bunch for FIQ mode. First and foremost you are confusing tasks and modes. At the application level the tasks will all share the same set of registers, there is no banking there, when you switch tasks you have to save registers, the operating system allocates memory for this and for each task switch saves the old tasks registers and restores the next tasks registers.
As far as register banking there are multiple r13s for example. For each access to the register there is more than a simple offset into the register file it also has other inputs, for example
unsigned int get_r13 ( unsigned int mode )
{
switch(mode)
{
case SYS: return r13_sys;
case SVC: return r13_svc;
case ABT: return r13_abt;
case UND: return r13_und;
case IRQ: return r13_irq;
case FIQ: return r13_fiq;
}
}
but in logic although the logic could very well look about the same, that or they take the mode bits and logically convert them into some of the address bits into the register file or a combination thereof.
A single register file does not mean there are only 16 registers (r0-r15, not counting cpsr, etc) in the register file, there are 31 or more depending on whether or not it contains *PSR registers.

Related

Are system registers banked per processor on ARMv8-A?

Are system registers banked per processor on ARMv8? I thought they weren't, which is why they were called system registers, but I'm now confused.
My understanding is that on multi-core ARMv8-A implementations different cores can be executing at different exception levels at any time. So what happens when you have different threads executing on different physical CPUs, each of which changing system registers according to their needs?
For example, I was reading about virtualization for a school project and saw some open source code, and I see system registers being saved and restored as part of "vCPU" thread contexts. If one core is executing a vCPU thread but another isn't, wouldn't they have conflicting system register states?
I would not use the work 'banked' in this context - a register in an arm core would be 'banked' in the case there would be different copies of the same register accessible depending on the core state.
For example, in an Armv8-A core, TTBR0_EL1 is accessible from EL1, EL2, and EL3. TTBR0_EL2 is accessible from EL2 and EL3 - This is a way to model the fact that the conceptual system register TTBR0 is banked.
But all the system registers as defined in the Registers Armv8, for Armv8-A architecture profile Documentation are present in a Armv8-a core.
That is, in a multi-core system, each core does have its own set of the system registers as defined in the documentation referenced above: the "System Registers" could be more specifically called "Core System Registers" in this context.
If you think about it, the MSR and MRS instructions being executed in a specific core do affect the general purpose and system registers of the same core:
MRS x0, TTBR0_EL1 // Move TTBR0_EL1 into x0
MSR TTBR0_EL1, x0 // Move x0 into TTBR0_EL1

ARM modes when context switching a user process running on guest

It is my understanding (from this article) that on ARM, the hypervisor/VMM runs in HYP mode, the guest OS runs in SVC mode, and user processes on the guest run in USR mode.
When there is a context switch in the guest OS, say switching from one user process to another, does this trap all the way up to the VMM in HYP mode? And if so, what happens at each stage of the process, going from USR to to SVC to HYP modes?
Short answer: depends on the hypervisor, architecture permits both approaches.
A context switch on ARM would be switching the Page Table and invalidating the TLB.
To switch Page Table, you need to modify the register TTBR0 (user-space part) or TTBR1 (kernel-space. normally for Linux it never changes but some exotic OS might be different) which are accessed via the "co-processor" instructions.
To set TTBR0 you use the instruction "MRC" with CRn = 2.
Such coprocessor accesses can be trapped by a HYP, but not necessarily. It depends on whether you request them to be trapped or not. This is set in the "Hypervisor System Trap Register" (HSTR_EL2 on aarch64).
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0488d/CIHJFIHA.html
TLB invalidation instructions and cache maintenance operations are also implemented as coprocessor access instructions on ARMv7 (technically also on ARMv8 but the Architecture Reference Manual suggests to use human-readable mnemonics instead). For example, "TLBIALL" is coprocessor CRn8 so you need to set bit T8 in HSTR_EL2.
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0438i/CIHECHCD.html

What does 'bank'ing a register mean?

Reading 'ARM Architecture' on Wikipedia and found the following statement:
Registers R0-R7 are the same across all CPU modes; they are never
banked.
R13 and R14 are banked across all privileged CPU modes except system
mode.
What does banking a register mean?
Register banking refers to providing multiple copies of a register at the same address.
Taken from section 1.4.6 of the arm docs
The term is referring to a solution for the problem that not all registers can be seen at once.
There is a different register bank for each processor mode. The banked registers give rapid context switching for dealing with processor exceptions and privileged operations.
If your looking for a more theoretical reasoning, I recommend this paper.
Edit: A much deeper answer than mine is given here
When the processor enters an exception, the banked registers are switched automatically with another set of these registers.
Virtually, the exception handler routine doesn't have to save these registers on the stack to prevent them from being clobbered later on (by the exception handler functions). The processor just keeps a safe copy of that set; and will restore the original set on exception return.
This clip explains it well
https://youtu.be/7LqPJGnBPMM?t=1419
Banked registers are registers which are not needed and accessible by the current execution mode. When the execution mode changes, the registers needed for the new mode will become usable.

ARM modes: User and System

Can you explain how the ARM mode get changed in case of a system call handling?
I heard ARM mode change can happen only in privileged mode, but in case of a system call handling while the ARM is in user mode (which is a non-privileged mode), how does the ARM mode change?
Can anybody explain the whole action flow for the user mode case, and also more generally the system call handling (especially how the ARM mode change)?
Thanks in advance.
In the case of system calls on ARM, normally the system call causes a SWI instruction to be executed. Anytime the processor executes a SWI (software interrupt) instruction, it goes into SVC mode, which is privileged, and jumps to the SWI exception handler. The SWI handler then looks at the cause of the interrupt (embedded in the instruction) and then does whatever the OS programmer decided it should do. The other exceptions - reset, undefined instruction, prefetch abort, data abort, interrupt, and fast interrupt - all also cause the processor to enter privileged modes.
How file handling works is entirely up to whoever wrote your operating system - there's nothing ARM specific about that at all.
You need to get a copy of the ARM ARM (Architectural Reference Manual).
http://infocenter.arm.com -> ARM Architecture -> Reference Manuals -> ARMv5 Architectural Reference Manual then download the pdf.
It used to be a single ARM ARM for the ARM world but there are too many cores and starting to diverge so they split off the old one as ARMv5 ARM and made new Architectural Reference Manuals for each of the major ARM processor families.
In the Programmers Model chapter it talks about the modes, it says that you can change freely among the modes other than user. ARM startup code will often go through a series of mode changes so that the stack pointers, etc can be configured. Then as needed go back to System mode or User mode.
In that same chapter look at the Exceptions section, this describes the exceptions and what mode the processor switches to for each exception.
The Software interrupt exception which happens when an SWI instruction is executed, is a way to implement system calls. The processor is put in Supervisor mode and if in thumb mode switches to arm mode.
There needs to be code to support that exception handler of course. You need to verify with the operating system, if any, you are running, what is supported and what the calling convention is, etc.
Not all ARM processors work this way. The Cortex-M (ARMv7-M) does not have the same modes and same exception table, etc. As with any time you are using an ARM (at this level) you need to get the ARM ARM for the family you are using and you need to get the TRM (Techincal Reference Manual) for the core(s) you are using, ideally the exact revision, even if ARM marks the TRM as having been replaced by a newer version the chip manufacturer has purchased and uses a specific rev of the core and there can be enough differences between revs that you will want the correct manual.
When an SVC instruction is encountered by the PC, the following behaviour takes place:
The current status (CPSR) is saved (to the supervisor SPSR)
The mode is switched to supervisor mode
Normal (IRQ) interrupts are disabled
ARM mode is entered (if not already in use)
The address of the following instruction (the return address) is saved into the link register (R14) - It's worth noting that this is
the link register that belongs to the supervisor mode
The PC is altered to jump to address 0x00000008
An exception vector (just a branch instruction) should be at the address 0x0000008, which will branch the program to another area of code used to determine which supervisor call has been made.
Determining which supervisor call has been made is usually accomplished by loading the SVC instruction into a register (by offsetting the LR by one word - since the LR is still pointing to the instruction next to the supervisor call), bit clearing the last 8 bits and using the value in the remaining 24 bits of the register to calculate an offset in a jump table, to branch to the corresponding SVC code.
When the supervisor call code wishes to return to the user application, the processor needs to context switch back into user mode and return to the address contained within the LR (which is only available in supervisor mode, since certain registers are banked for both modes). This problem is overcome using the MOVS instruction, as illustrated below:
(consider this to also be your explanation on how to change mode)
MRS R0, CPSR ; load CPSR into R0
BIC R0, R0, #&1F ; clear mode field
ORR R0, R0, #&10 ; user mode code
MSR SPSR, R0 ; store modified CPSR into SPSR
MOVS PC, LR ; context switch and branch
The MRS and MSR instructions are used to transfer content between an ARM register and the CPSR or SPSR.
The MOVS instruction is a special instruction, which operates as a standard MOV instruction, but also sets the CPSR equal to the SPSR upon branching. This allows the processor to branch back (since we're moving the LR into the PC) and change mode to the mode specified by the SPSR.
I quote from the ARM documentation available here:
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0471c/BABDCIEH.html
When an exception is generated, the processor performs the following
actions:
Copies the CPSR into the appropriate SPSR. This saves the current mode, interrupt mask, and condition flags.
Switches state automatically if the current state does not match the instruction set used in the exception vector table.
Changes the appropriate CPSR mode bits to:
Change to the appropriate mode, and map in the appropriate banked out registers for that mode.
Disable interrupts. IRQs are disabled when any exception occurs. FIQs are disabled when an FIQ occurs and on reset.
Sets the appropriate LR to the return address.
Sets the PC to the vector address for the exception.
where, CPSR refers to Current Program Status Register and SPSR to Saved Program Status register used to restore the state of the process that was interrupted. Thus, as seen in point 3, the processor circuitry is designed in a way that the hardware itself changes the mode when user mode executes a Supervisor call instruction.
"I heard ARM mode change can happen only in privileged mode". You are partly right here. By partly I mean the control field of the CPSR register can be manually modified (manually modified means through code) in the privileged modes only not in the unprivileged mode (i.e. user mode). When a system call happens in the user mode it happens because of SWI instruction. An SWI instruction has inbuilt mechanism to change the mode to supervisor mode.
So to conclude , there are two ways to change the mode:
1) Explicitly through code. Only allowed in a privileged mode.
2) Implicitly through IRQ, FIQ, SWI, RESET, undefined instruction encountered, data abort, prefetch abort. This is allowed in all the modes.

ARM modes and why are there so many?

I'm currently reading/learning about ARM architecture ...
and I was wondering why there are so many modes
(FIQ, User, System, Supervisor, IRQ, ...).
My question is why do we need so many modes? Wouldn't just User and System be enough?
Thanks in advance.
It's just an architectural decision. The big advantage of the multiple modes is that they have some banked registers. Those extra registers allow you to write much less complicated exception routines.
If you were to pick only two, just USR and SYS are probably as good a choice as any, but what would happen when you took an exception? The normal ARM model is to go to an exception mode, set the banked link register for that exception mode to point to the instruction you want to return to after you resolve the exception, save the processor state in the exception mode's SPSR register, and then jump to the exception vector. USR and SYS share all their registers - using this model, you'd blow away your function return address (in LR) every time you took an interrupt!
The FIQ mode in particular has even more banked registers than the other exception modes. Those extra registers are in keeping with the "F" part of FIQ - it stands for "Fast". Not having to save and restore more processor context in software will speed up your interrupt handler.
Not too much to add to Carl's answer. Not sure what family / architecture of ARM processors you're talking about, so I'll just assume based on your question (FIQ, IRQ, etc.) that you're talking about ARM7/9/11. I won't enumerate every difference between every mode in every ARM architecture variant.
In addition to what Carl said, a few other advantages of having different modes for different circumstances:
for example, in the FIQ, you don't have to branch off right away, you can just keep on executing. With other exceptions you have to branch right away
with different modes, you have natural support for separate stacks. If you're multitasking (e.g., RTOS) and you don't have a separate stack when you're in an interrupt mode, you have to build-in extra space onto each task stack for the worst-case interrupt situation
with different modes, certain registers (e.g. CPSR, MMU regs, etc. - depends on architecture) are off-limits. Same thing with certain instructions. You don't want to let user code modify privileged registers, now do you?

Resources