risc-v/riscv_swint.c: Simplify implementation of dispatch_syscall
Simplifies the implementation of dispatch_syscall, making it easier to understand and maintain. Let the C-compiler do most of the work, instead of doing everything as inline assembly.
This commit is contained in:
parent
fa71bc3d74
commit
2cf8ac2f63
@ -48,16 +48,74 @@
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_LIB_SYSCALL
|
||||
# define TCB_FLAGS_OFFSET offsetof(struct tcb_s, flags)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_LIB_SYSCALL
|
||||
|
||||
/****************************************************************************
|
||||
* Name: do_syscall
|
||||
*
|
||||
* Description:
|
||||
* Call the stub function corresponding to the system call. NOTE the non-
|
||||
* standard parameter passing:
|
||||
*
|
||||
* A0 = SYS_ call number
|
||||
* A1 = parm0
|
||||
* A2 = parm1
|
||||
* A3 = parm2
|
||||
* A4 = parm3
|
||||
* A5 = parm4
|
||||
* A6 = parm5
|
||||
*
|
||||
* Note:
|
||||
* Do not allow the compiler to inline this function, as it does a jump to
|
||||
* another procedure which can clobber any register and the compiler will
|
||||
* not understand it happens.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static uintptr_t do_syscall(unsigned int nbr, uintptr_t parm1,
|
||||
uintptr_t parm2, uintptr_t parm3,
|
||||
uintptr_t parm4, uintptr_t parm5,
|
||||
uintptr_t parm6) noinline_function;
|
||||
static uintptr_t do_syscall(unsigned int nbr, uintptr_t parm1,
|
||||
uintptr_t parm2, uintptr_t parm3,
|
||||
uintptr_t parm4, uintptr_t parm5,
|
||||
uintptr_t parm6)
|
||||
{
|
||||
register long a0 asm("a0") = (long)(nbr);
|
||||
register long a1 asm("a1") = (long)(parm1);
|
||||
register long a2 asm("a2") = (long)(parm2);
|
||||
register long a3 asm("a3") = (long)(parm3);
|
||||
register long a4 asm("a4") = (long)(parm4);
|
||||
register long a5 asm("a5") = (long)(parm5);
|
||||
register long a6 asm("a6") = (long)(parm6);
|
||||
|
||||
asm volatile
|
||||
(
|
||||
"la t0, g_stublookup\n" /* t0=The base of the stub lookup table */
|
||||
#ifdef CONFIG_ARCH_RV32
|
||||
"slli a0, a0, 2\n" /* a0=Offset for the stub lookup table */
|
||||
#else
|
||||
"slli a0, a0, 3\n" /* a0=Offset for the stub lookup table */
|
||||
#endif
|
||||
"add t0, t0, a0\n" /* t0=The address in the table */
|
||||
REGLOAD " t0, 0(t0)\n" /* t0=The address of the stub for this syscall */
|
||||
"jalr ra, t0\n" /* Call the stub (modifies ra) */
|
||||
: "+r"(a0)
|
||||
: "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5), "r"(a6)
|
||||
: "t0", "ra", "memory"
|
||||
);
|
||||
|
||||
return a0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: dispatch_syscall
|
||||
*
|
||||
@ -87,7 +145,7 @@ uintptr_t dispatch_syscall(unsigned int nbr, uintptr_t parm1,
|
||||
register long a4 asm("a4") = (long)(parm4);
|
||||
register long a5 asm("a5") = (long)(parm5);
|
||||
register long a6 asm("a6") = (long)(parm6);
|
||||
|
||||
register struct tcb_s *rtcb asm("tp");
|
||||
uintptr_t ret;
|
||||
|
||||
/* Valid system call ? */
|
||||
@ -99,37 +157,21 @@ uintptr_t dispatch_syscall(unsigned int nbr, uintptr_t parm1,
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/* ra gets clobbered below, but it does not matter */
|
||||
/* Indicate that we are in a syscall handler */
|
||||
|
||||
asm volatile
|
||||
(
|
||||
REGLOAD " t0, %1(tp)\n" /* Load tcb->flags */
|
||||
"ori t0, t0, %2\n" /* tcb->flags |= TCB_FLAG_SYSCALL */
|
||||
REGSTORE " t0, %1(tp)\n"
|
||||
"addi a0, a0, -%3\n" /* Offset a0 to account for the reserved syscalls */
|
||||
"la t0, g_stublookup\n" /* t0=The base of the stub lookup table */
|
||||
#ifdef CONFIG_ARCH_RV32
|
||||
"slli a0, a0, 2\n" /* a0=Offset for the stub lookup table */
|
||||
#else
|
||||
"slli a0, a0, 3\n" /* a0=Offset for the stub lookup table */
|
||||
#endif
|
||||
"add t0, t0, a0\n" /* t0=The address in the table */
|
||||
REGLOAD " t0, 0(t0)\n" /* t0=The address of the stub for this syscall */
|
||||
"jalr ra, t0\n" /* Call the stub (modifies ra) */
|
||||
REGLOAD " t0, %1(tp)\n" /* Load tcb->flags */
|
||||
"andi t0, t0, ~%2\n" /* tcb->flags &= ~TCB_FLAG_SYSCALL */
|
||||
REGSTORE " t0, %1(tp)\n"
|
||||
: "+r"(a0)
|
||||
: "i"(TCB_FLAGS_OFFSET),
|
||||
"i"(TCB_FLAG_SYSCALL),
|
||||
"i"(CONFIG_SYS_RESERVED),
|
||||
"r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5), "r"(a6)
|
||||
: "t0", "memory"
|
||||
);
|
||||
rtcb->flags |= TCB_FLAG_SYSCALL;
|
||||
|
||||
/* a0 gets clobbered below, save it locally here */
|
||||
/* Offset a0 to account for the reserved syscalls */
|
||||
|
||||
ret = a0;
|
||||
a0 -= CONFIG_SYS_RESERVED;
|
||||
|
||||
/* Run the system call, save return value locally */
|
||||
|
||||
ret = do_syscall(a0, a1, a2, a3, a4, a5, a6);
|
||||
|
||||
/* System call is now done */
|
||||
|
||||
rtcb->flags &= ~TCB_FLAG_SYSCALL;
|
||||
|
||||
/* Unmask any pending signals now */
|
||||
|
||||
@ -139,10 +181,6 @@ uintptr_t dispatch_syscall(unsigned int nbr, uintptr_t parm1,
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: riscv_swint
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user