93 lines
2.7 KiB
C
93 lines
2.7 KiB
C
/*
|
|
* Copyright (c) 2022 Intel Corporation.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <string.h>
|
|
|
|
#include <zephyr/arch/xtensa/syscall.h>
|
|
|
|
#include <zephyr/internal/syscall_handler.h>
|
|
#include <xtensa_internal.h>
|
|
|
|
#ifdef CONFIG_XTENSA_SYSCALL_USE_HELPER
|
|
uintptr_t xtensa_syscall_helper(uintptr_t arg1, uintptr_t arg2,
|
|
uintptr_t arg3, uintptr_t arg4,
|
|
uintptr_t arg5, uintptr_t arg6,
|
|
uintptr_t call_id)
|
|
{
|
|
register uintptr_t a2 __asm__("%a2") = call_id;
|
|
register uintptr_t a6 __asm__("%a6") = arg1;
|
|
register uintptr_t a3 __asm__("%a3") = arg2;
|
|
register uintptr_t a4 __asm__("%a4") = arg3;
|
|
register uintptr_t a5 __asm__("%a5") = arg4;
|
|
register uintptr_t a8 __asm__("%a8") = arg5;
|
|
register uintptr_t a9 __asm__("%a9") = arg6;
|
|
|
|
__asm__ volatile("syscall\n\t"
|
|
: "=r" (a2)
|
|
: "r" (a2), "r" (a6), "r" (a3), "r" (a4),
|
|
"r" (a5), "r" (a8), "r" (a9)
|
|
: "memory");
|
|
|
|
return a2;
|
|
}
|
|
#endif /* CONFIG_XTENSA_SYSCALL_USE_HELPER */
|
|
|
|
#if XCHAL_HAVE_THREADPTR == 0
|
|
#include <xtensa/config/core-isa.h>
|
|
#include <xtensa/config/core.h>
|
|
|
|
bool xtensa_is_user_context(void)
|
|
{
|
|
uint32_t ret;
|
|
|
|
__asm__ volatile(".global xtensa_is_user_context_epc\n"
|
|
" xtensa_is_user_context_epc:\n"
|
|
" syscall\n"
|
|
" mov %0, a2\n"
|
|
: "=r"(ret) : : "a2");
|
|
|
|
return ret != 0;
|
|
}
|
|
#endif /* XCHAL_HAVE_THREADPTR */
|
|
|
|
size_t arch_user_string_nlen(const char *s, size_t maxsize, int *err_arg)
|
|
{
|
|
/* Check if we can actually read the whole length.
|
|
*
|
|
* arch_user_string_nlen() is supposed to naively go through
|
|
* the string passed from user thread, and relies on page faults
|
|
* to catch inaccessible strings, such that user thread can pass
|
|
* a string that is shorter than the max length this function
|
|
* caller expects. So at least we want to make sure kernel has
|
|
* access to the whole length, aka. memory being mapped.
|
|
* Note that arch_user_string_nlen() should never result in
|
|
* thread termination due to page faults, and must always
|
|
* return to the caller with err_arg set or cleared.
|
|
* For MMU systems, unmapped memory will result in a DTLB miss
|
|
* and that might trigger an infinite DTLB miss storm if
|
|
* the corresponding L2 page table never exists in the first
|
|
* place (which would result in DTLB misses through L1 page
|
|
* table), until some other exceptions occur to break
|
|
* the cycle.
|
|
* For MPU systems, this would simply results in access errors
|
|
* and the exception handler will terminate the thread.
|
|
*/
|
|
if (!xtensa_mem_kernel_has_access((void *)s, maxsize, 0)) {
|
|
/*
|
|
* API says we need to set err_arg to -1 if there are
|
|
* any errors.
|
|
*/
|
|
*err_arg = -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* No error and we can proceed to getting the string length. */
|
|
*err_arg = 0;
|
|
|
|
return strnlen(s, maxsize);
|
|
}
|