From e7c3ca61fd2a13fe8d1623e7cdd215f17eedf13c Mon Sep 17 00:00:00 2001 From: Shell Date: Fri, 15 Sep 2023 15:57:08 +0800 Subject: [PATCH] [smart] fix rt_memcpy to lwp_memcpy in smart source (#8033) --- .../lwp/arch/aarch64/cortex-a/lwp_arch.c | 8 +- components/lwp/arch/arm/cortex-a/lwp_arch.c | 10 +- components/lwp/arch/risc-v/rv64/lwp_arch.c | 10 +- components/lwp/lwp.c | 8 +- components/lwp/lwp_syscall.c | 22 ++-- components/lwp/lwp_user_mm.c | 74 +++++++++-- components/lwp/lwp_user_mm.h | 121 ++++++++++++++++-- 7 files changed, 207 insertions(+), 46 deletions(-) diff --git a/components/lwp/arch/aarch64/cortex-a/lwp_arch.c b/components/lwp/arch/aarch64/cortex-a/lwp_arch.c index 593c19d8ee..fbb50bfdca 100644 --- a/components/lwp/arch/aarch64/cortex-a/lwp_arch.c +++ b/components/lwp/arch/aarch64/cortex-a/lwp_arch.c @@ -140,20 +140,20 @@ void *arch_signal_ucontext_save(rt_base_t user_sp, siginfo_t *psiginfo, /* push psiginfo */ if (psiginfo) { - memcpy(&new_sp->si, psiginfo, sizeof(*psiginfo)); + lwp_memcpy(&new_sp->si, psiginfo, sizeof(*psiginfo)); } /* exp frame is already aligned as AAPCS64 required */ - memcpy(&new_sp->frame, exp_frame, sizeof(*exp_frame)); + lwp_memcpy(&new_sp->frame, exp_frame, sizeof(*exp_frame)); /* copy the save_sig_mask */ - memcpy(&new_sp->save_sigmask, save_sig_mask, sizeof(lwp_sigset_t)); + lwp_memcpy(&new_sp->save_sigmask, save_sig_mask, sizeof(lwp_sigset_t)); /* copy lwp_sigreturn */ const size_t lwp_sigreturn_bytes = 8; extern void lwp_sigreturn(void); /* -> ensure that the sigreturn start at the outer most boundary */ - memcpy(&new_sp->sigreturn, &lwp_sigreturn, lwp_sigreturn_bytes); + lwp_memcpy(&new_sp->sigreturn, &lwp_sigreturn, lwp_sigreturn_bytes); } else { diff --git a/components/lwp/arch/arm/cortex-a/lwp_arch.c b/components/lwp/arch/arm/cortex-a/lwp_arch.c index 0c97d6831a..d1fcf63d93 100644 --- a/components/lwp/arch/arm/cortex-a/lwp_arch.c +++ b/components/lwp/arch/arm/cortex-a/lwp_arch.c @@ -69,7 +69,7 @@ void arch_kuser_init(rt_aspace_t aspace, void *vectors) while (1) ; // early failed - rt_memcpy((void *)((char *)vectors + 0x1000 - kuser_sz), __kuser_helper_start, kuser_sz); + lwp_memcpy((void *)((char *)vectors + 0x1000 - kuser_sz), __kuser_helper_start, kuser_sz); /* * vectors + 0xfe0 = __kuser_get_tls * vectors + 0xfe8 = hardware TLS instruction at 0xffff0fe8 @@ -171,22 +171,22 @@ void *arch_signal_ucontext_save(rt_base_t lr, siginfo_t *psiginfo, /* push psiginfo */ if (psiginfo) { - memcpy(&new_sp->si, psiginfo, sizeof(*psiginfo)); + lwp_memcpy(&new_sp->si, psiginfo, sizeof(*psiginfo)); } - memcpy(&new_sp->frame.r0_to_r12, exp_frame, sizeof(new_sp->frame.r0_to_r12) + sizeof(rt_base_t)); + lwp_memcpy(&new_sp->frame.r0_to_r12, exp_frame, sizeof(new_sp->frame.r0_to_r12) + sizeof(rt_base_t)); new_sp->frame.lr = lr; __asm__ volatile("mrs %0, spsr":"=r"(spsr)); new_sp->frame.spsr = spsr; /* copy the save_sig_mask */ - memcpy(&new_sp->save_sigmask, save_sig_mask, sizeof(lwp_sigset_t)); + lwp_memcpy(&new_sp->save_sigmask, save_sig_mask, sizeof(lwp_sigset_t)); /* copy lwp_sigreturn */ extern void lwp_sigreturn(void); /* -> ensure that the sigreturn start at the outer most boundary */ - memcpy(&new_sp->sigreturn, &lwp_sigreturn, lwp_sigreturn_bytes); + lwp_memcpy(&new_sp->sigreturn, &lwp_sigreturn, lwp_sigreturn_bytes); } else { diff --git a/components/lwp/arch/risc-v/rv64/lwp_arch.c b/components/lwp/arch/risc-v/rv64/lwp_arch.c index 04d56a47e1..9a88709668 100644 --- a/components/lwp/arch/risc-v/rv64/lwp_arch.c +++ b/components/lwp/arch/risc-v/rv64/lwp_arch.c @@ -49,7 +49,7 @@ void *lwp_copy_return_code_to_user_stack() { rt_size_t size = (rt_size_t)lwp_thread_return_end - (rt_size_t)lwp_thread_return; rt_size_t userstack = (rt_size_t)tid->user_stack + tid->user_stack_size - size; - rt_memcpy((void *)userstack, lwp_thread_return, size); + lwp_memcpy((void *)userstack, lwp_thread_return, size); return (void *)userstack; } @@ -290,19 +290,19 @@ void *arch_signal_ucontext_save(int signo, siginfo_t *psiginfo, /* push psiginfo */ if (psiginfo) { - memcpy(&new_sp->si, psiginfo, sizeof(*psiginfo)); + lwp_memcpy(&new_sp->si, psiginfo, sizeof(*psiginfo)); } - memcpy(&new_sp->frame, exp_frame, sizeof(*exp_frame)); + lwp_memcpy(&new_sp->frame, exp_frame, sizeof(*exp_frame)); /* copy the save_sig_mask */ - memcpy(&new_sp->save_sigmask, save_sig_mask, sizeof(lwp_sigset_t)); + lwp_memcpy(&new_sp->save_sigmask, save_sig_mask, sizeof(lwp_sigset_t)); /* copy lwp_sigreturn */ const size_t lwp_sigreturn_bytes = 8; extern void lwp_sigreturn(void); /* -> ensure that the sigreturn start at the outer most boundary */ - memcpy(&new_sp->sigreturn, &lwp_sigreturn, lwp_sigreturn_bytes); + lwp_memcpy(&new_sp->sigreturn, &lwp_sigreturn, lwp_sigreturn_bytes); /** * synchronize dcache & icache if target is diff --git a/components/lwp/lwp.c b/components/lwp/lwp.c index ee5d05a33c..858662fb99 100644 --- a/components/lwp/lwp.c +++ b/components/lwp/lwp.c @@ -200,7 +200,7 @@ struct process_aux *lwp_argscopy(struct rt_lwp *lwp, int argc, char **argv, char { len = rt_strlen(argv[i]) + 1; new_argve[i] = str; - rt_memcpy(str_k, argv[i], len); + lwp_memcpy(str_k, argv[i], len); str += len; str_k += len; } @@ -216,7 +216,7 @@ struct process_aux *lwp_argscopy(struct rt_lwp *lwp, int argc, char **argv, char { len = rt_strlen(envp[j]) + 1; new_argve[i] = str; - rt_memcpy(str_k, envp[j], len); + lwp_memcpy(str_k, envp[j], len); str += len; str_k += len; i++; @@ -298,7 +298,7 @@ static struct process_aux *lwp_argscopy(struct rt_lwp *lwp, int argc, char **arg { len = rt_strlen(argv[i]) + 1; new_argve[i] = str; - rt_memcpy(str, argv[i], len); + lwp_memcpy(str, argv[i], len); str += len; } new_argve[i] = 0; @@ -312,7 +312,7 @@ static struct process_aux *lwp_argscopy(struct rt_lwp *lwp, int argc, char **arg { len = rt_strlen(envp[j]) + 1; new_argve[i] = str; - rt_memcpy(str, envp[j], len); + lwp_memcpy(str, envp[j], len); str += len; i++; } diff --git a/components/lwp/lwp_syscall.c b/components/lwp/lwp_syscall.c index 2d9e0c0bed..0b82910d39 100644 --- a/components/lwp/lwp_syscall.c +++ b/components/lwp/lwp_syscall.c @@ -1715,7 +1715,7 @@ long _sys_clone(void *arg[]) rt_hw_interrupt_enable(level); /* copy origin stack */ - rt_memcpy(thread->stack_addr, self->stack_addr, thread->stack_size); + lwp_memcpy(thread->stack_addr, self->stack_addr, thread->stack_size); lwp_tid_set_thread(tid, thread); arch_set_thread_context(arch_clone_exit, (void *)((char *)thread->stack_addr + thread->stack_size), @@ -1899,7 +1899,7 @@ sysret_t _sys_fork(void) rt_hw_interrupt_enable(level); /* copy origin stack */ - rt_memcpy(thread->stack_addr, self_thread->stack_addr, self_thread->stack_size); + lwp_memcpy(thread->stack_addr, self_thread->stack_addr, self_thread->stack_size); lwp_tid_set_thread(tid, thread); /* duplicate user objects */ @@ -2037,7 +2037,7 @@ static char *_insert_args(int new_argc, char *new_argv[], struct lwp_args_info * { nargv[i] = p; len = rt_strlen(new_argv[i]) + 1; - rt_memcpy(p, new_argv[i], len); + lwp_memcpy(p, new_argv[i], len); p += len; } /* copy argv */ @@ -2046,7 +2046,7 @@ static char *_insert_args(int new_argc, char *new_argv[], struct lwp_args_info * { nargv[i] = p; len = rt_strlen(args->argv[i]) + 1; - rt_memcpy(p, args->argv[i], len); + lwp_memcpy(p, args->argv[i], len); p += len; } nargv[i] = NULL; @@ -2055,7 +2055,7 @@ static char *_insert_args(int new_argc, char *new_argv[], struct lwp_args_info * { nenvp[i] = p; len = rt_strlen(args->envp[i]) + 1; - rt_memcpy(p, args->envp[i], len); + lwp_memcpy(p, args->envp[i], len); p += len; } nenvp[i] = NULL; @@ -2238,7 +2238,7 @@ int load_ldso(struct rt_lwp *lwp, char *exec_name, char *const argv[], char *con { kargv[i] = p; len = rt_strlen(argv[i]) + 1; - rt_memcpy(p, argv[i], len); + lwp_memcpy(p, argv[i], len); p += len; } kargv[i] = NULL; @@ -2250,7 +2250,7 @@ int load_ldso(struct rt_lwp *lwp, char *exec_name, char *const argv[], char *con { kenvp[i] = p; len = rt_strlen(envp[i]) + 1; - rt_memcpy(p, envp[i], len); + lwp_memcpy(p, envp[i], len); p += len; } kenvp[i] = NULL; @@ -2431,7 +2431,7 @@ sysret_t sys_execve(const char *path, char *const argv[], char *const envp[]) { kargv[i] = p; len = rt_strlen(argv[i]) + 1; - rt_memcpy(p, argv[i], len); + lwp_memcpy(p, argv[i], len); p += len; } kargv[i] = NULL; @@ -2443,7 +2443,7 @@ sysret_t sys_execve(const char *path, char *const argv[], char *const envp[]) { kenvp[i] = p; len = rt_strlen(envp[i]) + 1; - rt_memcpy(p, envp[i], len); + lwp_memcpy(p, envp[i], len); p += len; } kenvp[i] = NULL; @@ -3393,7 +3393,7 @@ sysret_t sys_sigaction(int sig, const struct k_sigaction *act, } kact.sa_flags = act->flags; kact.__sa_handler._sa_handler = act->handler; - memcpy(&kact.sa_mask, &act->mask, sigsetsize); + lwp_memcpy(&kact.sa_mask, &act->mask, sigsetsize); kact.sa_restorer = act->restorer; pkact = &kact; } @@ -3933,7 +3933,7 @@ sysret_t sys_gethostbyname2_r(const char *name, int af, struct hostent *ret, while (sal_he.h_addr_list[index] != NULL) { ret->h_addr_list[index] = ptr; - rt_memcpy(ptr, sal_he.h_addr_list[index], sal_he.h_length); + lwp_memcpy(ptr, sal_he.h_addr_list[index], sal_he.h_length); ptr += sal_he.h_length; index++; diff --git a/components/lwp/lwp_user_mm.c b/components/lwp/lwp_user_mm.c index 0bbfcafcf3..7fa061c5d4 100644 --- a/components/lwp/lwp_user_mm.c +++ b/components/lwp/lwp_user_mm.c @@ -11,6 +11,7 @@ * 2021-02-19 lizhirui add riscv64 support for lwp_user_accessable and lwp_get_from_user * 2021-06-07 lizhirui modify user space bound check * 2022-12-25 wangxiaoyao adapt to new mm + * 2023-09-13 Shell Add lwp_memcpy and support run-time choice of memcpy base on memory attr */ #include @@ -624,6 +625,63 @@ size_t lwp_put_to_user(void *dst, void *src, size_t size) return lwp_data_put(lwp, dst, src, size); } +rt_inline rt_bool_t _in_user_space(const char *addr) +{ + return (addr >= (char *)USER_VADDR_START && addr < (char *)USER_VADDR_TOP); +} + +rt_inline rt_bool_t _can_unaligned_access(const char *addr) +{ + return rt_kmem_v2p((char *)addr) - PV_OFFSET == addr; +} + +void *lwp_memcpy(void * __restrict dst, const void * __restrict src, size_t size) +{ + void *rc = dst; + long len; + + if (_in_user_space(dst)) + { + if (!_in_user_space(src)) + { + len = lwp_put_to_user(dst, (void *)src, size); + if (!len) + { + LOG_E("lwp_put_to_user(lwp=%p, dst=%p,src=%p,size=0x%lx) failed", lwp_self(), dst, src, size); + } + } + else + { + /* not support yet */ + LOG_W("%s(dst=%p,src=%p,size=0x%lx): operation not support", dst, src, size, __func__); + } + } + else + { + if (_in_user_space(src)) + { + len = lwp_get_from_user(dst, (void *)src, size); + if (!len) + { + LOG_E("lwp_get_from_user(lwp=%p, dst=%p,src=%p,size=0x%lx) failed", lwp_self(), dst, src, size); + } + } + else + { + if (_can_unaligned_access(dst) && _can_unaligned_access(src)) + { + rc = memcpy(dst, src, size); + } + else + { + rt_memcpy(dst, src, size); + } + } + } + + return rc; +} + int lwp_user_accessible_ext(struct rt_lwp *lwp, void *addr, size_t size) { void *addr_start = RT_NULL, *addr_end = RT_NULL, *next_page = RT_NULL; @@ -631,11 +689,11 @@ int lwp_user_accessible_ext(struct rt_lwp *lwp, void *addr, size_t size) if (!lwp) { - return 0; + return RT_FALSE; } if (!size || !addr) { - return 0; + return RT_FALSE; } addr_start = addr; addr_end = (void *)((char *)addr + size); @@ -643,16 +701,16 @@ int lwp_user_accessible_ext(struct rt_lwp *lwp, void *addr, size_t size) #ifdef ARCH_RISCV64 if (addr_start < (void *)USER_VADDR_START) { - return 0; + return RT_FALSE; } #else if (addr_start >= (void *)USER_VADDR_TOP) { - return 0; + return RT_FALSE; } if (addr_end > (void *)USER_VADDR_TOP) { - return 0; + return RT_FALSE; } #endif @@ -677,16 +735,16 @@ int lwp_user_accessible_ext(struct rt_lwp *lwp, void *addr, size_t size) .fault_vaddr = addr_start, }; if (!rt_aspace_fault_try_fix(lwp->aspace, &msg)) - return 0; + return RT_FALSE; } else - return 0; + return RT_FALSE; } addr_start = (void *)((char *)addr_start + len); size -= len; next_page = (void *)((char *)next_page + ARCH_PAGE_SIZE); } while (addr_start < addr_end); - return 1; + return RT_TRUE; } int lwp_user_accessable(void *addr, size_t size) diff --git a/components/lwp/lwp_user_mm.h b/components/lwp/lwp_user_mm.h index 66f3ebc4b2..b052723e71 100644 --- a/components/lwp/lwp_user_mm.h +++ b/components/lwp/lwp_user_mm.h @@ -28,6 +28,117 @@ extern "C" { #define LWP_MAP_FLAG_NONE 0x0000 #define LWP_MAP_FLAG_NOCACHE 0x0001 +/** + * @brief Map files or devices into memory + * It will create a new mapping in the virtual address space of the target lwp + * + * @param lwp target process + * @param addr address from user space + * @param length length in bytes of mapping + * @param prot protect attribution of mapping + * @param flags flags of control + * @param fd file descriptor + * @param pgoffset offset to fd in 4096 bytes unit + * @return void* the address is successful, otherwise return MAP_FAILED + */ +void* lwp_mmap2(void *addr, size_t length, int prot, int flags, int fd, off_t pgoffset); + +/** + * @brief Unmap memory region in user space + * + * @param lwp target process + * @param addr address to unmap + * @param length length in bytes of unmapping + * @return int errno + */ +int lwp_munmap(void *addr); + +/** + * @brief Test if address from user is accessible address by user + * + * @param lwp target process + * @param addr address from user space + * @param size the bytes to access + * @return int RT_FALSE/RT_TRUE + */ +int lwp_user_accessible_ext(struct rt_lwp *lwp, void *addr, size_t size); + +/** + * @brief Test if address from user is accessible address by user + * Same as lwp_user_accessible_ext except that lwp is current lwp + * + * @param addr address from user space + * @param size the bytes to access + * @return int RT_FALSE/RT_TRUE + */ +int lwp_user_accessable(void *addr, size_t size); + +/** + * @brief Copy n bytes data from src to dst. + * Same as std libc memcpy, except that both src and dst may come from + * user space. lwp_memcpy will test and select the implementation based + * on the memory attribution on run-time + * + * @param dst where the data writes to + * @param src where the data comes from + * @param size the bytes to copy + * @return void* the destination address + */ +void *lwp_memcpy(void * __restrict dst, const void * __restrict src, size_t size); + +/** + * @brief memcpy from address in user address space to kernel space buffer + * + * @param lwp target process + * @param dst kernel space address where the data writes to + * @param src user space address where the data comes from + * @param size the bytes to copy + * @return size_t the bytes copied + */ +size_t lwp_data_get(struct rt_lwp *lwp, void *dst, void *src, size_t size); + +/** + * @brief lwp_data_get except that lwp is current lwp + * + * @param dst kernel space address where the data writes to + * @param src user space address where the data comes from + * @param size the bytes to copy + * @return size_t the bytes copied + */ +size_t lwp_get_from_user(void *dst, void *src, size_t size); + +/** + * @brief memcpy from kernel space buffer to address in user address space + * + * @param lwp target process + * @param dst user space address where the data writes to + * @param src kernel space address where the data comes from + * @param size the bytes to copy + * @return size_t the bytes copied + */ +size_t lwp_data_put(struct rt_lwp *lwp, void *dst, void *src, size_t size); + +/** + * @brief lwp_data_put except that lwp is current lwp + * + * @param dst user space address where the data writes to + * @param src kernel space address where the data comes from + * @param size the bytes to copy + * @return size_t the bytes copied + */ +size_t lwp_put_to_user(void *dst, void *src, size_t size); + +/** + * @brief memset to address in user address space + * + * @param lwp target process + * @param dst user space address where the data writes to + * @param c the value to write + * @param size the bytes to copy + * @return size_t the bytes written + */ +size_t lwp_data_set(struct rt_lwp *lwp, void *dst, int c, size_t size); + int lwp_user_space_init(struct rt_lwp *lwp, rt_bool_t is_fork); void lwp_unmap_user_space(struct rt_lwp *lwp); @@ -35,6 +146,7 @@ int lwp_unmap_user(struct rt_lwp *lwp, void *va); void *lwp_map_user(struct rt_lwp *lwp, void *map_va, size_t map_size, rt_bool_t text); rt_varea_t lwp_map_user_varea(struct rt_lwp *lwp, void *map_va, size_t map_size); + /* check LWP_MAP_FLAG_* */ rt_varea_t lwp_map_user_varea_ext(struct rt_lwp *lwp, void *map_va, size_t map_size, size_t flags); @@ -42,16 +154,7 @@ void *lwp_map_user_phy(struct rt_lwp *lwp, void *map_va, void *map_pa, size_t ma int lwp_unmap_user_phy(struct rt_lwp *lwp, void *va); rt_base_t lwp_brk(void *addr); -void* lwp_mmap2(void *addr, size_t length, int prot, int flags, int fd, off_t pgoffset); -int lwp_munmap(void *addr); -size_t lwp_get_from_user(void *dst, void *src, size_t size); -size_t lwp_put_to_user(void *dst, void *src, size_t size); -int lwp_user_accessable(void *addr, size_t size); -int lwp_user_accessible_ext(struct rt_lwp *lwp, void *addr, size_t size); - -size_t lwp_data_get(struct rt_lwp *lwp, void *dst, void *src, size_t size); -size_t lwp_data_put(struct rt_lwp *lwp, void *dst, void *src, size_t size); void lwp_data_cache_flush(struct rt_lwp *lwp, void *vaddr, size_t size); static inline void *_lwp_v2p(struct rt_lwp *lwp, void *vaddr)