ARM System Calls: Difference between revisions

From OSDev.wiki
Jump to navigation Jump to search
[unchecked revision][unchecked revision]
Content added Content deleted
No edit summary
No edit summary
Line 2: Line 2:
==System Calls==
==System Calls==


<pre>swi 42</pre>
<pre>swi 0x420000</pre>
This is how you call the system on ARM. The instruction `swi` jumps to a predefined address, which in turn jumps to the system call handler. The system call handler executes the specific function and return to the user code with:
This is how you call the system on ARM. The instruction <span style="font-family:monospace">swi</span> jumps to a predefined address, which in turn jumps to the system call handler. The system call handler executes the specific function and return to the user code with:
<pre>subs pc, lr, #4</pre>
<pre>mov pc, lr</pre>
Most of the time you won't need to worry about returning from the interrupt, as GCC, set up to cross compile for ARM, lets you code the interrupt handlers in C:
Most of the time you won't need to worry about returning from the interrupt, as GCC, set up to cross compile for ARM, lets you code the interrupt handlers in C:
<source lang="c">void swi_handler () __attribute__((interrupt));</source>
<source lang="c">void swi_handler () __attribute__((interrupt));</source>
Line 19: Line 19:
b . @ FIQ
b . @ FIQ
</pre>
</pre>
This is the ARM equivalent to the IDT, on the x86, and it is stored at address 0. The only entry, we need to worry about is the SWI Handler. To install our own SWI handler, we replace the "b ." instruction with a branch to our handler:
This is the ARM equivalent to the IDT, on the x86, and it is stored at address 0. The only entry, we need to worry about is the SWI Handler. To install our own SWI handler, we replace the <span style="font-family:monospace">b .</span> instruction with a branch to our handler:
<pre>
<pre>
interrupt_vector_table:
interrupt_vector_table:
Line 38: Line 38:
void __attribute__ ((interrupt ("SWI"))) swi_handler (int r0, int r1, int r2, int r3) {}
void __attribute__ ((interrupt ("SWI"))) swi_handler (int r0, int r1, int r2, int r3) {}
</source>
</source>
You have probably noticed from the first example "swi 42", that the "swi" instruction takes an integer as an argument. To get this argument from the C code, you do:
You have probably noticed from the first example (<span style="font-family:monospace">swi 0x420000</span>), that swi takes an integer as an argument. For it to work in both ARM and THUMB modes of the processor, the integer must be left shifted by 16. To get this integer in the C code, do this:
<source lang="c">
<source lang="c">
uint32_t int_vector = 0;
uint8_t int_vector = 0;
asm volatile ("ldr %0, [lr, #-8]" : "=r" (int_vector));
asm volatile ("ldrb %0, [lr, #-2]" : "=r" (int_vector));
int_vector &= 0xFFFFFF;
</source>
</source>
We only need the first 24-bits, because the last 8-bits are those of the "swi" instruction, 0xEF.
[[Category:ARM]]
[[Category:ARM]]
[[Category:In Progress]]
[[Category:In Progress]]

Revision as of 13:15, 29 May 2010

This page is a work in progress.
This page may thus be incomplete. Its content may be changed in the near future.

System Calls

swi 0x420000

This is how you call the system on ARM. The instruction swi jumps to a predefined address, which in turn jumps to the system call handler. The system call handler executes the specific function and return to the user code with:

mov pc, lr

Most of the time you won't need to worry about returning from the interrupt, as GCC, set up to cross compile for ARM, lets you code the interrupt handlers in C:

void swi_handler () __attribute__((interrupt));

Creating System Calls

interrupt_vector_table:
    b . @ Reset Handler
    b . @ Undefined
    b . @ SWI Handler
    b . @ Prefetch Abort
    b . @ Data Abort
    b . @ IRQ
    b . @ FIQ

This is the ARM equivalent to the IDT, on the x86, and it is stored at address 0. The only entry, we need to worry about is the SWI Handler. To install our own SWI handler, we replace the b . instruction with a branch to our handler:

interrupt_vector_table:
    b . @ Reset Handler
    b . @ Undefined
    b swi_handler @ Our new SWI Handler
    b . @ Prefetch Abort
    b . @ Data Abort
    b . @ IRQ
    b . @ FIQ

We can code the interrupt handler like this:

void __attribute__ ((interrupt ("SWI"))) swi_handler (void) {}

Parameters to functions on ARM, are passed in registers r0-r3, if follow the same convention for system calls, then our interrupt handler can take parameters:

void __attribute__ ((interrupt ("SWI"))) swi_handler (int r0, int r1, int r2, int r3) {}

You have probably noticed from the first example (swi 0x420000), that swi takes an integer as an argument. For it to work in both ARM and THUMB modes of the processor, the integer must be left shifted by 16. To get this integer in the C code, do this:

uint8_t int_vector = 0;
asm volatile ("ldrb %0, [lr, #-2]" : "=r" (int_vector));