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:
Ville Juven 2024-07-31 13:32:57 +03:00 committed by Xiang Xiao
parent fa71bc3d74
commit 2cf8ac2f63

View File

@ -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
*