voron

experimental ARM OS
git clone git://git.2f30.org/voron
Log | Files | Refs | README | LICENSE

commit 3014676a7f3803961c64c177f9dc6ea3eaec157f
parent 69e2d993a545881d6e15a59b29e88d82b9e223fd
Author: oblique <psyberbits@gmail.com>
Date:   Sun, 18 Aug 2013 06:44:46 +0300

Use the same calling convetion that Linux kernel use for syscalls.

SWI/SVC handler use Linux ARM EABI calling convention:
r0 - r6 registers are used for the syscall arguments, it can take up to 7 arguments.
r7 register is used for the syscall number.
"swi #0" is used from calling the syscall.

Diffstat:
Mkernel/interrupts.S | 51+++++++++++++++++++++++++++++++--------------------
Mkernel/start.S | 36+++++++++++++++++++++++++++---------
Mkernel/syscall_table.S | 7++++++-
Mkernel/syscalls.c | 32++++++++++++++++++--------------
4 files changed, 82 insertions(+), 44 deletions(-)

diff --git a/kernel/interrupts.S b/kernel/interrupts.S @@ -1,4 +1,5 @@ #include <p_modes.h> +#include <errno.h> .section .text .global vector_table_init @@ -73,29 +74,39 @@ reset: undefined_insn: movs pc, lr -/* system call number is the swi number - * if system call takes less than 7 arguments - * we use r0 until r5 from userland to pass them - * if it takes more than 6 arguments we pass a - * pointer of the arguments at r0 - */ +@@ SWI/SVC handler use Linux ARM EABI calling convention: +@@ r0 - r6 registers are used for the syscall arguments, it can take up to 7 arguments. +@@ r7 register is used for the syscall number. swi_ex: - stmfd sp!, { r6 - r12, lr } - mrs r6, spsr - str r6, [sp, #-4]! - - ldr r6, [lr, #-4] - bic r6, r6, #0xff000000 - - stmfd sp!, { r4, r5 } + @@ save r8 - r12, lr registers + stmfd sp!, { r8 - r12, lr } + @@ save spsr register + mrs r8, spsr + str r8, [sp, #-4]! + + @@ calculate the number of system calls + ldr r8, =syscall_table_end + ldr r8, [r8] + lsr r8, r8, #2 + + @@ if syscall number is out of syscall table boundaries then return -ENOSYS + cmp r7, r8 + movcs r0, #-ENOSYS + bcs 2f + + @@ prepare arguments and call the system call + stmfd sp!, { r4 - r6 } ldr lr, =1f - ldr r7, =syscall_table - ldr pc, [r7, r6, lsl #2] + ldr r8, =syscall_table + ldr pc, [r8, r7, lsl #2] + + @@ return from SWI/SVC exception handler 1: - add sp, sp, #8 - ldr r6, [sp], #4 - msr spsr, r6 - ldmfd sp!, { r6 - r12, pc }^ + add sp, sp, #(4 * 3) +2: + ldr r8, [sp], #4 + msr spsr, r8 + ldmfd sp!, { r8 - r12, pc }^ prefetch_abort: @@ save registers diff --git a/kernel/start.S b/kernel/start.S @@ -67,28 +67,46 @@ _start: b 1b 3: - /* example of calling a system call with at least 6 arguments */ + @@ example of calling a system call with 1 argument + mov r0, #1 + @@ the syscall number is 0 + mov r7, #0 + swi #0 + + @@ example of calling a system call with 4 arguments + mov r0, #1 + mov r1, #2 + mov r2, #3 + mov r3, #4 + @@ the syscall number is 0 + mov r7, #1 + swi #0 + + @@ example of calling a system call with 5 arguments mov r0, #1 mov r1, #2 mov r2, #3 mov r3, #4 mov r4, #5 - mov r5, #6 + @@ the syscall number is 0 + mov r7, #2 swi #0 - /* example of calling a system call with more than 6 arguments */ - mov r0, #7 - str r0, [sp, #-4]! + @@ example of calling a system call with 7 arguments mov r0, #1 mov r1, #2 mov r2, #3 mov r3, #4 mov r4, #5 mov r5, #6 - stmfd sp!, { r0 - r5 } - mov r0, sp - swi #1 - add sp, sp, #(7 * 4) + mov r6, #7 + @@ the syscall number is 0 + mov r7, #3 + swi #0 + + @@ out of boundary syscall number example + mov r7, #1000 + swi #0 ldr r0, =kmain mov r1, #0 diff --git a/kernel/syscall_table.S b/kernel/syscall_table.S @@ -1,5 +1,10 @@ .section .text .globl syscall_table +.globl syscall_table_end syscall_table: - .word sys_test_6_args + .word sys_test_1_args + .word sys_test_4_args + .word sys_test_5_args .word sys_test_7_args +syscall_table_end: + .word . - syscall_table diff --git a/kernel/syscalls.c b/kernel/syscalls.c @@ -1,26 +1,30 @@ #include <kernel.h> long -sys_test_6_args(u32 a1, u32 a2, u32 a3, u32 a4, u32 a5, u32 a6) +sys_test_1_args(u32 a1) { - kprintf("sys_test_6_args(%d, %d, %d, %d, %d, %d)\n", a1, a2, a3, a4, a5, a6); + kprintf("sys_test_1_args(%d)\n", a1); return 0; } -struct __test_7_args { - u32 a1; - u32 a2; - u32 a3; - u32 a4; - u32 a5; - u32 a6; - u32 a7; -}; long -sys_test_7_args(struct __test_7_args *a) +sys_test_4_args(u32 a1, u32 a2, u32 a3, u32 a4) { - kprintf("sys_test_7_args(%d, %d, %d, %d, %d, %d, %d)\n", - a->a1, a->a2, a->a3, a->a4, a->a5, a->a6, a->a7); + kprintf("sys_test_4_args(%d, %d, %d, %d)\n", a1, a2, a3, a4); + return 0; +} + +long +sys_test_5_args(u32 a1, u32 a2, u32 a3, u32 a4, u32 a5) +{ + kprintf("sys_test_5_args(%d, %d, %d, %d, %d)\n", a1, a2, a3, a4, a5); + return 0; +} + +long +sys_test_7_args(u32 a1, u32 a2, u32 a3, u32 a4, u32 a5, u32 a6, u32 a7) +{ + kprintf("sys_test_7_args(%d, %d, %d, %d, %d, %d, %d)\n", a1, a2, a3, a4, a5, a6, a7); return 0; }