diff options
| author | guo <[email protected]> | 2022-12-03 12:07:44 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2022-12-03 12:07:44 +0800 |
| commit | ecf2d8215961ca7c539132b62a72df6072cc3e14 (patch) | |
| tree | 59005f0f74f2593c0435059264f624c862a89f55 /components/lwp/arch | |
| parent | aaf5462c6d4ae9466a0a8cd2a4bb00cfe1fef2f2 (diff) | |
sync branch rt-smart. (#6641)
* Synchronize the code of the rt mart branch to the master branch.
* TTY device
* Add lwP code from rt-smart
* Add vnode in DFS, but DFS will be re-write for rt-smart
* There are three libcpu for rt-smart:
* arm/cortex-a, arm/aarch64
* riscv64
Co-authored-by: Rbb666 <[email protected]>
Co-authored-by: zhkag <[email protected]>
Diffstat (limited to 'components/lwp/arch')
29 files changed, 2756 insertions, 1305 deletions
diff --git a/components/lwp/arch/aarch64/common/reloc.c b/components/lwp/arch/aarch64/common/reloc.c new file mode 100644 index 0000000000..4057a5718b --- /dev/null +++ b/components/lwp/arch/aarch64/common/reloc.c @@ -0,0 +1,28 @@ +#include <rtthread.h> +#include <stdint.h> +#include <string.h> +#include <elf.h> +#ifdef RT_USING_USERSPACE +#include <mmu.h> +#include <page.h> +#endif + +#define Elf_Word Elf64_Word +#define Elf_Addr Elf64_Addr +#define Elf_Half Elf64_Half +#define Elf_Ehdr Elf64_Ehdr #define Elf_Phdr Elf64_Phdr +#define Elf_Shdr Elf64_Shdr + +typedef struct +{ + Elf_Word st_name; + Elf_Addr st_value; + Elf_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf_Half st_shndx; +} Elf_sym; + +void arch_elf_reloc(void *text_start, void *rel_dyn_start, size_t rel_dyn_size, void *got_start, size_t got_size, Elf_sym *dynsym) +{ +} diff --git a/components/lwp/arch/aarch64/cortex-a/lwp_arch.c b/components/lwp/arch/aarch64/cortex-a/lwp_arch.c new file mode 100644 index 0000000000..c5f4cebdb9 --- /dev/null +++ b/components/lwp/arch/aarch64/cortex-a/lwp_arch.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-05-18 Jesven first version + */ + +#include <rtthread.h> +#include <rthw.h> + +#ifdef RT_USING_USERSPACE + +#include <mmu.h> +#include <page.h> +#include <lwp_mm_area.h> +#include <lwp_user_mm.h> +#include <lwp_arch.h> + +extern size_t MMUTable[]; + +int arch_user_space_init(struct rt_lwp *lwp) +{ + size_t *mmu_table; + + mmu_table = (size_t*)rt_pages_alloc(0); + if (!mmu_table) + { + return -1; + } + + lwp->end_heap = USER_HEAP_VADDR; + memset(mmu_table, 0, ARCH_PAGE_SIZE); + rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, mmu_table, ARCH_PAGE_SIZE); + rt_hw_mmu_map_init(&lwp->mmu_info, (void*)USER_VADDR_START, USER_VADDR_TOP - USER_VADDR_START, mmu_table, PV_OFFSET); + + return 0; +} + +void *arch_kernel_mmu_table_get(void) +{ + return (void*)NULL; +} + +void arch_kuser_init(rt_mmu_info *mmu_info, void *vectors) +{ +} + +void arch_user_space_vtable_free(struct rt_lwp *lwp) +{ + if (lwp && lwp->mmu_info.vtable) + { + rt_pages_free(lwp->mmu_info.vtable, 0); + } +} + +int arch_expand_user_stack(void *addr) +{ + int ret = 0; + size_t stack_addr = (size_t)addr; + + stack_addr &= ~ARCH_PAGE_MASK; + if ((stack_addr >= (size_t)USER_STACK_VSTART) && (stack_addr < (size_t)USER_STACK_VEND)) + { + void *map = lwp_map_user(lwp_self(), (void*)stack_addr, ARCH_PAGE_SIZE, 0); + + if (map || lwp_user_accessable(addr, 1)) + { + ret = 1; + } + } + return ret; +} + +#endif diff --git a/components/lwp/arch/aarch64/cortex-a/lwp_arch.h b/components/lwp/arch/aarch64/cortex-a/lwp_arch.h new file mode 100644 index 0000000000..98dcd989b1 --- /dev/null +++ b/components/lwp/arch/aarch64/cortex-a/lwp_arch.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-05-18 Jesven first version + */ + +#ifndef LWP_ARCH_H__ +#define LWP_ARCH_H__ + +#include <lwp.h> +#include <lwp_arch_comm.h> + +#ifdef RT_USING_USERSPACE + +#define USER_VADDR_TOP 0x0001000000000000UL +#define USER_HEAP_VEND 0x0000ffffB0000000UL +#define USER_HEAP_VADDR 0x0000ffff80000000UL +#define USER_STACK_VSTART 0x0000ffff70000000UL +#define USER_STACK_VEND USER_HEAP_VADDR +#define LDSO_LOAD_VADDR 0x60000000UL +#define USER_VADDR_START 0x00200000UL +#define USER_LOAD_VADDR USER_VADDR_START + +#ifdef __cplusplus +extern "C" { +#endif + +unsigned long rt_hw_ffz(unsigned long x); + +rt_inline void icache_invalid_all(void) +{ + asm volatile ("ic ialluis\n\tisb sy":::"memory"); +} + +#ifdef __cplusplus +} +#endif + +#endif + +#endif /*LWP_ARCH_H__*/ diff --git a/components/lwp/arch/aarch64/cortex-a/lwp_gcc.S b/components/lwp/arch/aarch64/cortex-a/lwp_gcc.S new file mode 100644 index 0000000000..c873cd5357 --- /dev/null +++ b/components/lwp/arch/aarch64/cortex-a/lwp_gcc.S @@ -0,0 +1,593 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-05-18 Jesven first version + */ + +#include "rtconfig.h" + +#include "asm-fpu.h" + +/********************* + * SPSR BIT * + *********************/ + +#define SPSR_Mode(v) ((v) << 0) +#define SPSR_A64 (0 << 4) +#define SPSR_RESEVRED_5 (0 << 5) +#define SPSR_FIQ_MASKED(v) ((v) << 6) +#define SPSR_IRQ_MASKED(v) ((v) << 7) +#define SPSR_SERROR_MASKED(v) ((v) << 8) +#define SPSR_D_MASKED(v) ((v) << 9) +#define SPSR_RESEVRED_10_19 (0 << 10) +#define SPSR_IL(v) ((v) << 20) +#define SPSR_SS(v) ((v) << 21) +#define SPSR_RESEVRED_22_27 (0 << 22) +#define SPSR_V(v) ((v) << 28) +#define SPSR_C(v) ((v) << 29) +#define SPSR_Z(v) ((v) << 30) +#define SPSR_N(v) ((v) << 31) + +/********************* + * CONTEXT_OFFSET * + *********************/ + +#define CONTEXT_OFFSET_ELR_EL1 0x0 +#define CONTEXT_OFFSET_SPSR_EL1 0x8 +#define CONTEXT_OFFSET_SP_EL0 0x10 +#define CONTEXT_OFFSET_X30 0x18 +#define CONTEXT_OFFSET_FPCR 0x20 +#define CONTEXT_OFFSET_FPSR 0x28 +#define CONTEXT_OFFSET_X28 0x30 +#define CONTEXT_OFFSET_X29 0x38 +#define CONTEXT_OFFSET_X26 0x40 +#define CONTEXT_OFFSET_X27 0x48 +#define CONTEXT_OFFSET_X24 0x50 +#define CONTEXT_OFFSET_X25 0x58 +#define CONTEXT_OFFSET_X22 0x60 +#define CONTEXT_OFFSET_X23 0x68 +#define CONTEXT_OFFSET_X20 0x70 +#define CONTEXT_OFFSET_X21 0x78 +#define CONTEXT_OFFSET_X18 0x80 +#define CONTEXT_OFFSET_X19 0x88 +#define CONTEXT_OFFSET_X16 0x90 +#define CONTEXT_OFFSET_X17 0x98 +#define CONTEXT_OFFSET_X14 0xa0 +#define CONTEXT_OFFSET_X15 0xa8 +#define CONTEXT_OFFSET_X12 0xb0 +#define CONTEXT_OFFSET_X13 0xb8 +#define CONTEXT_OFFSET_X10 0xc0 +#define CONTEXT_OFFSET_X11 0xc8 +#define CONTEXT_OFFSET_X8 0xd0 +#define CONTEXT_OFFSET_X9 0xd8 +#define CONTEXT_OFFSET_X6 0xe0 +#define CONTEXT_OFFSET_X7 0xe8 +#define CONTEXT_OFFSET_X4 0xf0 +#define CONTEXT_OFFSET_X5 0xf8 +#define CONTEXT_OFFSET_X2 0x100 +#define CONTEXT_OFFSET_X3 0x108 +#define CONTEXT_OFFSET_X0 0x110 +#define CONTEXT_OFFSET_X1 0x118 + +#define CONTEXT_OFFSET_Q15 0x120 +#define CONTEXT_OFFSET_Q14 0x130 +#define CONTEXT_OFFSET_Q13 0x140 +#define CONTEXT_OFFSET_Q12 0x150 +#define CONTEXT_OFFSET_Q11 0x160 +#define CONTEXT_OFFSET_Q10 0x170 +#define CONTEXT_OFFSET_Q9 0x180 +#define CONTEXT_OFFSET_Q8 0x190 +#define CONTEXT_OFFSET_Q7 0x1a0 +#define CONTEXT_OFFSET_Q6 0x1b0 +#define CONTEXT_OFFSET_Q5 0x1c0 +#define CONTEXT_OFFSET_Q4 0x1d0 +#define CONTEXT_OFFSET_Q3 0x1e0 +#define CONTEXT_OFFSET_Q2 0x1f0 +#define CONTEXT_OFFSET_Q1 0x200 +#define CONTEXT_OFFSET_Q0 0x210 + +#define CONTEXT_FPU_SIZE 0x100 +#define CONTEXT_SIZE 0x220 + +/**************************************************/ + +.text + +/* + * void arch_start_umode(args, text, ustack, kstack); + */ +.global arch_start_umode +.type arch_start_umode, % function +arch_start_umode: + mov sp, x3 + mov x4, #(SPSR_Mode(0) | SPSR_A64) + mov x3, x2 ;/* user stack top */ + msr daifset, #3 + dsb sy + mrs x30, sp_el0 + msr spsr_el1, x4 + msr elr_el1, x1 + eret + +/* + * void arch_crt_start_umode(args, text, ustack, kstack); + */ +.global arch_crt_start_umode +.type arch_crt_start_umode, % function +arch_crt_start_umode: + sub x4, x2, #0x10 + adr x2, lwp_thread_return + ldr x5, [x2] + str x5, [x4] + ldr x5, [x2, #4] + str x5, [x4, #4] + ldr x5, [x2, #8] + str x5, [x4, #8] + + mov x5, x4 + dc cvau, x5 + add x5, x5, #8 + dc cvau, x5 + dsb sy + ic ialluis + dsb sy + + msr sp_el0, x4 + + mov sp, x3 + mov x4, #(SPSR_Mode(0) | SPSR_A64) + msr daifset, #3 + dsb sy + mrs x30, sp_el0 + msr spsr_el1, x4 + msr elr_el1, x1 + eret + +/* +void arch_set_thread_context(void *exit_addr, void *new_thread_stack, void *user_stack, void **thread_sp); +*/ +.global arch_set_thread_context +arch_set_thread_context: + sub x1, x1, #CONTEXT_SIZE + str x2, [x1, #CONTEXT_OFFSET_SP_EL0] + sub x1, x1, #CONTEXT_SIZE + str xzr, [x1, #CONTEXT_OFFSET_X0] /* new thread return 0 */ + mov x4, #((3 << 6) | 0x4 | 0x1) /* el1h, disable interrupt */ + str x4, [x1, #CONTEXT_OFFSET_SPSR_EL1] + str x0, [x1, #CONTEXT_OFFSET_ELR_EL1] + str x1, [x3] + ret + +.global arch_get_user_sp +arch_get_user_sp: + mrs x0, sp_el0 + ret + +.global arch_fork_exit +.global arch_clone_exit +arch_fork_exit: +arch_clone_exit: + b arch_syscall_exit + +/* +void lwp_exec_user(void *args, void *kernel_stack, void *user_entry) +*/ +.global lwp_exec_user +lwp_exec_user: + mov sp, x1 + mov x4, #(SPSR_Mode(0) | SPSR_A64) + ldr x3, =0x0000ffff80000000 + msr daifset, #3 + msr spsr_el1, x4 + msr elr_el1, x2 + eret + +/* + * void SVC_Handler(regs); + */ +.global SVC_Handler +.type SVC_Handler, % function +SVC_Handler: + /* x0 is initial sp */ + mov sp, x0 + + msr daifclr, #3 /* enable interrupt */ + + bl rt_thread_self + bl lwp_user_setting_save + + ldp x8, x9, [sp, #(CONTEXT_OFFSET_X8)] + and x0, x8, #0xf000 + cmp x0, #0xe000 + beq arch_signal_quit + + cmp x0, #0xf000 + beq ret_from_user + + uxtb x0, w8 + bl lwp_get_sys_api + cmp x0, xzr + mov x30, x0 + beq arch_syscall_exit + ldp x0, x1, [sp, #(CONTEXT_OFFSET_X0)] + ldp x2, x3, [sp, #(CONTEXT_OFFSET_X2)] + ldp x4, x5, [sp, #(CONTEXT_OFFSET_X4)] + ldp x6, x7, [sp, #(CONTEXT_OFFSET_X6)] + blr x30 + /* jump explictly, make this code position independant */ + b arch_syscall_exit + +.global arch_syscall_exit +arch_syscall_exit: + msr daifset, #3 + + ldp x2, x3, [sp], #0x10 /* SPSR and ELR. */ + msr spsr_el1, x3 + msr elr_el1, x2 + + ldp x29, x30, [sp], #0x10 + msr sp_el0, x29 + ldp x28, x29, [sp], #0x10 + msr fpcr, x28 + msr fpsr, x29 + ldp x28, x29, [sp], #0x10 + ldp x26, x27, [sp], #0x10 + ldp x24, x25, [sp], #0x10 + ldp x22, x23, [sp], #0x10 + ldp x20, x21, [sp], #0x10 + ldp x18, x19, [sp], #0x10 + ldp x16, x17, [sp], #0x10 + ldp x14, x15, [sp], #0x10 + ldp x12, x13, [sp], #0x10 + ldp x10, x11, [sp], #0x10 + ldp x8, x9, [sp], #0x10 + add sp, sp, #0x40 + RESTORE_FPU sp + +.global arch_ret_to_user +arch_ret_to_user: + SAVE_FPU sp + stp x0, x1, [sp, #-0x10]! + stp x2, x3, [sp, #-0x10]! + stp x4, x5, [sp, #-0x10]! + stp x6, x7, [sp, #-0x10]! + stp x8, x9, [sp, #-0x10]! + stp x10, x11, [sp, #-0x10]! + stp x12, x13, [sp, #-0x10]! + stp x14, x15, [sp, #-0x10]! + stp x16, x17, [sp, #-0x10]! + stp x18, x19, [sp, #-0x10]! + stp x20, x21, [sp, #-0x10]! + stp x22, x23, [sp, #-0x10]! + stp x24, x25, [sp, #-0x10]! + stp x26, x27, [sp, #-0x10]! + stp x28, x29, [sp, #-0x10]! + + mrs x0, fpcr + mrs x1, fpsr + stp x0, x1, [sp, #-0x10]! + stp x29, x30, [sp, #-0x10]! + + bl lwp_check_debug + bl lwp_check_exit_request + cbz w0, 1f + mov x0, xzr + b sys_exit +1: + ldr x0, =rt_dbg_ops + ldr x0, [x0] + cbz x0, 3f + bl dbg_thread_in_debug + mov x1, #(1 << 21) + mrs x2, spsr_el1 + cbz w0, 2f + orr x2, x2, x1 + msr spsr_el1, x2 + b 3f +2: + bic x2, x2, x1 + msr spsr_el1, x2 +3: + bl lwp_signal_check + cmp x0, xzr + + ldp x29, x30, [sp], #0x10 + ldp x0, x1, [sp], #0x10 + msr fpcr, x0 + msr fpsr, x1 + + ldp x28, x29, [sp], #0x10 + ldp x26, x27, [sp], #0x10 + ldp x24, x25, [sp], #0x10 + ldp x22, x23, [sp], #0x10 + ldp x20, x21, [sp], #0x10 + ldp x18, x19, [sp], #0x10 + ldp x16, x17, [sp], #0x10 + ldp x14, x15, [sp], #0x10 + ldp x12, x13, [sp], #0x10 + ldp x10, x11, [sp], #0x10 + ldp x8, x9, [sp], #0x10 + ldp x6, x7, [sp], #0x10 + ldp x4, x5, [sp], #0x10 + ldp x2, x3, [sp], #0x10 + ldp x0, x1, [sp], #0x10 + RESTORE_FPU sp + + bne user_do_signal + + stp x0, x1, [sp, #-0x10]! + ldr x0, =rt_dbg_ops + ldr x0, [x0] + cmp x0, xzr + ldp x0, x1, [sp], #0x10 + beq 1f + SAVE_FPU sp + stp x0, x1, [sp, #-0x10]! + stp x2, x3, [sp, #-0x10]! + stp x4, x5, [sp, #-0x10]! + stp x6, x7, [sp, #-0x10]! + stp x8, x9, [sp, #-0x10]! + stp x10, x11, [sp, #-0x10]! + stp x12, x13, [sp, #-0x10]! + stp x14, x15, [sp, #-0x10]! + stp x16, x17, [sp, #-0x10]! + stp x18, x19, [sp, #-0x10]! + stp x20, x21, [sp, #-0x10]! + stp x22, x23, [sp, #-0x10]! + stp x24, x25, [sp, #-0x10]! + stp x26, x27, [sp, #-0x10]! + stp x28, x29, [sp, #-0x10]! + mrs x0, fpcr + mrs x1, fpsr + stp x0, x1, [sp, #-0x10]! + stp x29, x30, [sp, #-0x10]! + mrs x0, elr_el1 + bl dbg_attach_req + ldp x29, x30, [sp], #0x10 + ldp x0, x1, [sp], #0x10 + msr fpcr, x0 + msr fpsr, x1 + ldp x28, x29, [sp], #0x10 + ldp x26, x27, [sp], #0x10 + ldp x24, x25, [sp], #0x10 + ldp x22, x23, [sp], #0x10 + ldp x20, x21, [sp], #0x10 + ldp x18, x19, [sp], #0x10 + ldp x16, x17, [sp], #0x10 + ldp x14, x15, [sp], #0x10 + ldp x12, x13, [sp], #0x10 + ldp x10, x11, [sp], #0x10 + ldp x8, x9, [sp], #0x10 + ldp x6, x7, [sp], #0x10 + ldp x4, x5, [sp], #0x10 + ldp x2, x3, [sp], #0x10 + ldp x0, x1, [sp], #0x10 + RESTORE_FPU sp +1: + eret + +/* +struct rt_hw_exp_stack +{ + unsigned long pc; 0 + unsigned long cpsr; + unsigned long sp_el0; 0x10 + unsigned long x30; + unsigned long fpcr; 0x20 + unsigned long fpsr; + unsigned long x28; 0x30 + unsigned long x29; + unsigned long x26; 0x40 + unsigned long x27; + unsigned long x24; 0x50 + unsigned long x25; + unsigned long x22; 0x60 + unsigned long x23; + unsigned long x20; 0x70 + unsigned long x21; + unsigned long x18; 0x80 + unsigned long x19; + unsigned long x16; 0x90 + unsigned long x17; + unsigned long x14; 0xa0 + unsigned long x15; + unsigned long x12; 0xb0 + unsigned long x13; + unsigned long x10; 0xc0 + unsigned long x11; + unsigned long x8; 0xd0 + unsigned long x9; + unsigned long x6; 0xe0 + unsigned long x7; + unsigned long x4; 0xf0 + unsigned long x5; + unsigned long x2; 0x100 + unsigned long x3; + unsigned long x0; 0x110 + unsigned long x1; + + unsigned long long fpu[16]; 0x120 + 0x220 = 0x120 + 0x10 * 0x10 +}; +*/ +.global lwp_check_debug +lwp_check_debug: + ldr x0, =rt_dbg_ops + ldr x0, [x0] + cbnz x0, 1f + ret +1: + stp x29, x30, [sp, #-0x10]! + bl dbg_check_suspend + cbz w0, lwp_check_debug_quit + + mrs x2, sp_el0 + sub x2, x2, #0x10 + mov x3, x2 + msr sp_el0, x2 + ldr x0, =lwp_debugreturn + ldr w1, [x0] + str w1, [x2] + ldr w1, [x0, #4] + str w1, [x2, #4] + + dc cvau, x2 + add x2, x2, #4 + dc cvau, x2 + + dsb sy + isb sy + + ic ialluis + isb sy + + mrs x0, elr_el1 + mrs x1, spsr_el1 + stp x0, x1, [sp, #-0x10]! + msr elr_el1, x3 /* lwp_debugreturn */ + mov x1, #(SPSR_Mode(0) | SPSR_A64) + orr x1, x1, #(1 << 21) + msr spsr_el1, x1 + eret +ret_from_user: + /* sp_el0 += 16 for drop ins lwp_debugreturn */ + mrs x0, sp_el0 + add x0, x0, #0x10 + msr sp_el0, x0 + /* now is el1, sp is pos(empty) - sizeof(context) */ + mov x0, sp + add x0, x0, #0x220 + mov sp, x0 + ldp x0, x1, [sp], #0x10 /* x1 is origin spsr_el1 */ + msr elr_el1, x0 /* x0 is origin elr_el1 */ + msr spsr_el1, x1 +lwp_check_debug_quit: + ldp x29, x30, [sp], #0x10 + ret + +arch_signal_quit: + msr daifset, #3 +/* + drop stack data +*/ + add sp, sp, #CONTEXT_SIZE + bl lwp_signal_restore + /* x0 is user_ctx : ori sp, pc, cpsr */ + ldr x1, [x0] + ldr x2, [x0, #8] + ldr x3, [x0, #16] + msr spsr_el1, x3 + msr elr_el1, x2 + add x1, x1, #16 + msr sp_el0, x1 + + msr spsel, #0 + + ldp x29, x30, [sp], #0x10 + ldp x28, x29, [sp], #0x10 + msr fpcr, x28 + msr fpsr, x29 + ldp x28, x29, [sp], #0x10 + ldp x26, x27, [sp], #0x10 + ldp x24, x25, [sp], #0x10 + ldp x22, x23, [sp], #0x10 + ldp x20, x21, [sp], #0x10 + ldp x18, x19, [sp], #0x10 + ldp x16, x17, [sp], #0x10 + ldp x14, x15, [sp], #0x10 + ldp x12, x13, [sp], #0x10 + ldp x10, x11, [sp], #0x10 + ldp x8, x9, [sp], #0x10 + ldp x6, x7, [sp], #0x10 + ldp x4, x5, [sp], #0x10 + ldp x2, x3, [sp], #0x10 + ldp x0, x1, [sp], #0x10 + RESTORE_FPU sp + + msr spsel, #1 + + b arch_ret_to_user + +user_do_signal: + msr spsel, #0 + SAVE_FPU sp + stp x0, x1, [sp, #-0x10]! + stp x2, x3, [sp, #-0x10]! + stp x4, x5, [sp, #-0x10]! + stp x6, x7, [sp, #-0x10]! + stp x8, x9, [sp, #-0x10]! + stp x10, x11, [sp, #-0x10]! + stp x12, x13, [sp, #-0x10]! + stp x14, x15, [sp, #-0x10]! + stp x16, x17, [sp, #-0x10]! + stp x18, x19, [sp, #-0x10]! + stp x20, x21, [sp, #-0x10]! + stp x22, x23, [sp, #-0x10]! + stp x24, x25, [sp, #-0x10]! + stp x26, x27, [sp, #-0x10]! + stp x28, x29, [sp, #-0x10]! + mrs x28, fpcr + mrs x29, fpsr + stp x28, x29, [sp, #-0x10]! + stp x29, x30, [sp, #-0x10]! + + sub sp, sp, #0x10 + adr x0, lwp_sigreturn + ldr w1, [x0] + str w1, [sp] + ldr w1, [x0, #4] + str w1, [sp, #4] + + mov x20, sp /* lwp_sigreturn */ + mov x0, sp + + dc cvau, x0 + dsb sy + ic ialluis + dsb sy + + msr spsel, #1 + + mrs x1, elr_el1 + mrs x2, spsr_el1 + bl lwp_signal_backup + /* x0 is signal */ + mov x19, x0 + bl lwp_sighandler_get + adds x1, x0, xzr + mov x0, x19 + bne 1f + mov x1, x20 +1: + msr elr_el1, x1 + mov x30, x20 + eret + +lwp_debugreturn: + mov x8, 0xf000 + svc #0 + +lwp_sigreturn: + mov x8, #0xe000 + svc #0 + +lwp_thread_return: + mov x0, xzr + mov x8, #0x01 + svc #0 + +.globl arch_get_tidr +arch_get_tidr: + mrs x0, tpidr_el0 + ret + +.global arch_set_thread_area +arch_set_thread_area: +.globl arch_set_tidr +arch_set_tidr: + msr tpidr_el0, x0 + ret diff --git a/components/lwp/arch/arm/arm926/lwp_gcc.S b/components/lwp/arch/arm/arm926/lwp_gcc.S deleted file mode 100644 index 2a8ce492eb..0000000000 --- a/components/lwp/arch/arm/arm926/lwp_gcc.S +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2018-12-10 Jesven first version - */ - -#define Mode_USR 0x10 -#define Mode_FIQ 0x11 -#define Mode_IRQ 0x12 -#define Mode_SVC 0x13 -#define Mode_MON 0x16 -#define Mode_ABT 0x17 -#define Mode_UDF 0x1B -#define Mode_SYS 0x1F - -#define A_Bit 0x100 -#define I_Bit 0x80 @; when I bit is set, IRQ is disabled -#define F_Bit 0x40 @; when F bit is set, FIQ is disabled -#define T_Bit 0x20 - -.cpu arm9 -.syntax unified -.text - -/* - * void lwp_user_entry(args, text, data); - */ -.global lwp_user_entry -.type lwp_user_entry, % function -lwp_user_entry: - mrs r9, cpsr - mov r8, r9 - bic r9, #0x1f - orr r9, #Mode_USR - - orr r8, #I_Bit - msr cpsr_c, r8 - - msr spsr, r9 - - /* set data address. */ - mov r9, r2 - movs pc, r1 - -/* - * void SVC_Handler(void); - */ -.global SVC_Handler -.type SVC_Handler, % function -SVC_Handler: - push {lr} - mrs lr, spsr - push {r4, r5, lr} - - mrs r4, cpsr - bic r4, #I_Bit - msr cpsr_c, r4 - - push {r0 - r3, r12} - and r0, r7, #0xff - bl lwp_get_sys_api - cmp r0, #0 /* r0 = api */ - mov r4, r0 - pop {r0 - r3, r12} - beq svc_exit - ldr lr, = svc_exit - bx r4 - -svc_exit: - mrs r4, cpsr - orr r4, #I_Bit - msr cpsr_c, r4 - - pop {r4, r5, lr} - msr spsr_cxsf, lr - pop {lr} - movs pc, lr diff --git a/components/lwp/arch/arm/common/reloc.c b/components/lwp/arch/arm/common/reloc.c new file mode 100644 index 0000000000..a232df885d --- /dev/null +++ b/components/lwp/arch/arm/common/reloc.c @@ -0,0 +1,120 @@ +#include <rtthread.h> +#include <stdint.h> +#include <string.h> +#include <lwp_elf.h> +#ifdef RT_USING_USERSPACE +#include <mmu.h> +#include <page.h> +#endif + +typedef struct +{ + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; +} Elf32_sym; + +#ifdef RT_USING_USERSPACE +void arch_elf_reloc(rt_mmu_info *m_info, void *text_start, void *rel_dyn_start, size_t rel_dyn_size, void *got_start, size_t got_size, Elf32_sym *dynsym) +{ + size_t rel_off; + void* addr; + + if (rel_dyn_size && !dynsym) + { + return; + } + for (rel_off = 0; rel_off < rel_dyn_size; rel_off += 8) + { + uint32_t v1, v2; + + /* + memcpy(&v1, rel_dyn_start + rel_off, 4); + memcpy(&v2, rel_dyn_start + rel_off + 4, 4); + */ + + addr = rt_hw_mmu_v2p(m_info, (void*)((char*)rel_dyn_start + rel_off)); + addr = (void*)((char*)addr - PV_OFFSET); + memcpy(&v1, addr, 4); + addr = rt_hw_mmu_v2p(m_info, (void*)((char*)rel_dyn_start + rel_off + 4)); + addr = (void*)((char*)addr - PV_OFFSET); + memcpy(&v2, addr, 4); + + addr = rt_hw_mmu_v2p(m_info, (void*)((char*)text_start + v1)); + addr = (void*)((char*)addr - PV_OFFSET); + if ((v2 & 0xff) == R_ARM_RELATIVE) + { + // *(uint32_t*)(text_start + v1) += (uint32_t)text_start; + *(uint32_t*)addr += (uint32_t)text_start; + } + else if ((v2 & 0xff) == R_ARM_ABS32) + { + uint32_t t; + t = (v2 >> 8); + if (t) /* 0 is UDF */ + { + // *(uint32_t*)(text_start + v1) = (uint32_t)(text_start + dynsym[t].st_value); + *(uint32_t*)addr = (uint32_t)((char*)text_start + dynsym[t].st_value); + } + } + } + /* modify got */ + if (got_size) + { + uint32_t *got_item = (uint32_t*)got_start; + + for (rel_off = 0; rel_off < got_size; rel_off += 4, got_item++) + { + //*got_item += (uint32_t)text_start; + addr = rt_hw_mmu_v2p(m_info, got_item); + addr = (void*)((char*)addr - PV_OFFSET); + *(uint32_t *)addr += (uint32_t)text_start; + } + } +} +#else + +void arch_elf_reloc(void *text_start, void *rel_dyn_start, size_t rel_dyn_size, void *got_start, size_t got_size, Elf32_sym *dynsym) +{ + size_t rel_off; + + if (rel_dyn_size && !dynsym) + { + return; + } + for (rel_off = 0; rel_off < rel_dyn_size; rel_off += 8) + { + uint32_t v1, v2; + + memcpy(&v1, (void*)((char*)rel_dyn_start + rel_off), 4); + memcpy(&v2, (void*)((char*)rel_dyn_start + rel_off + 4), 4); + + if ((v2 & 0xff) == R_ARM_RELATIVE) + { + *(uint32_t*)((char*)text_start + v1) += (uint32_t)text_start; + } + else if ((v2 & 0xff) == R_ARM_ABS32) + { + uint32_t t; + t = (v2 >> 8); + if (t) /* 0 is UDF */ + { + *(uint32_t*)((char*)text_start + v1) = (uint32_t)((char*)text_start + dynsym[t].st_value); + } + } + } + /* modify got */ + if (got_size) + { + uint32_t *got_item = (uint32_t*)got_start; + + for (rel_off = 0; rel_off < got_size; rel_off += 4, got_item++) + { + *got_item += (uint32_t)text_start; + } + } +} +#endif diff --git a/components/lwp/arch/arm/cortex-a/lwp_arch.c b/components/lwp/arch/arm/cortex-a/lwp_arch.c new file mode 100644 index 0000000000..814c1513ed --- /dev/null +++ b/components/lwp/arch/arm/cortex-a/lwp_arch.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-10-28 Jesven first version + */ + +#include <rtthread.h> +#include <rthw.h> + +#ifdef RT_USING_USERSPACE + +#include <mmu.h> +#include <page.h> +#include <lwp_mm_area.h> +#include <lwp_user_mm.h> +#include <lwp_arch.h> + +extern size_t MMUTable[]; + +int arch_user_space_init(struct rt_lwp *lwp) +{ + size_t *mmu_table; + + mmu_table = (size_t*)rt_pages_alloc(2); + if (!mmu_table) + { + return -1; + } + + lwp->end_heap = USER_HEAP_VADDR; + rt_memcpy(mmu_table + (KERNEL_VADDR_START >> ARCH_SECTION_SHIFT), MMUTable + (KERNEL_VADDR_START >> ARCH_SECTION_SHIFT), ARCH_PAGE_SIZE); + rt_memset(mmu_table, 0, 3 * ARCH_PAGE_SIZE); + rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, mmu_table, 4 * ARCH_PAGE_SIZE); + rt_hw_mmu_map_init(&lwp->mmu_info, (void*)USER_VADDR_START, USER_VADDR_TOP - USER_VADDR_START, mmu_table, PV_OFFSET); + + return 0; +} + +void *arch_kernel_mmu_table_get(void) +{ + return (void*)((char*)MMUTable + PV_OFFSET); +} + +void arch_kuser_init(rt_mmu_info *mmu_info, void *vectors) +{ + extern char __kuser_helper_start[], __kuser_helper_end[]; + int kuser_sz = __kuser_helper_end - __kuser_helper_start; + + rt_hw_mmu_map_auto(mmu_info, vectors, 0x1000, MMU_MAP_U_RO); + + rt_memcpy((void*)((char*)vectors + 0x1000 - kuser_sz), __kuser_helper_start, kuser_sz); + /* + * vectors + 0xfe0 = __kuser_get_tls + * vectors + 0xfe8 = hardware TLS instruction at 0xffff0fe8 + */ + rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, (void*)((char*)vectors + 0x1000 - kuser_sz), kuser_sz); + rt_hw_cpu_icache_ops(RT_HW_CACHE_INVALIDATE, (void*)((char*)vectors + 0x1000 - kuser_sz), kuser_sz); +} + +void arch_user_space_vtable_free(struct rt_lwp *lwp) +{ + if (lwp && lwp->mmu_info.vtable) + { + rt_pages_free(lwp->mmu_info.vtable, 2); + } +} + +int arch_expand_user_stack(void *addr) +{ + int ret = 0; + size_t stack_addr = (size_t)addr; + + stack_addr &= ~ARCH_PAGE_MASK; + if ((stack_addr >= (size_t)USER_STACK_VSTART) && (stack_addr < (size_t)USER_STACK_VEND)) + { + void *map = lwp_map_user(lwp_self(), (void*)stack_addr, ARCH_PAGE_SIZE, 0); + + if (map || lwp_user_accessable(addr, 1)) + { + ret = 1; + } + } + return ret; +} + +#ifdef LWP_ENABLE_ASID +#define MAX_ASID_BITS 8 +#define MAX_ASID (1 << MAX_ASID_BITS) +static uint64_t global_generation = 1; +static char asid_valid_bitmap[MAX_ASID]; +unsigned int arch_get_asid(struct rt_lwp *lwp) +{ + if (lwp == RT_NULL) + { + // kernel + return 0; + } + + if (lwp->generation == global_generation) + { + return lwp->asid; + } + + if (lwp->asid && !asid_valid_bitmap[lwp->asid]) + { + asid_valid_bitmap[lwp->asid] = 1; + return lwp->asid; + } + + for (unsigned i = 1; i < MAX_ASID; i++) + { + if (asid_valid_bitmap[i] == 0) + { + asid_valid_bitmap[i] = 1; + lwp->generation = global_generation; + lwp->asid = i; + return lwp->asid; + } + } + + global_generation++; + memset(asid_valid_bitmap, 0, MAX_ASID * sizeof(char)); + + asid_valid_bitmap[1] = 1; + lwp->generation = global_generation; + lwp->asid = 1; + + asm volatile ("mcr p15, 0, r0, c8, c7, 0\ndsb\nisb" ::: "memory"); + + return lwp->asid; +} +#endif + +#endif diff --git a/components/lwp/arch/arm/cortex-a/lwp_arch.h b/components/lwp/arch/arm/cortex-a/lwp_arch.h new file mode 100644 index 0000000000..d627632493 --- /dev/null +++ b/components/lwp/arch/arm/cortex-a/lwp_arch.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + */ + +#ifndef LWP_ARCH_H__ +#define LWP_ARCH_H__ + +#include <lwp.h> +#include <lwp_arch_comm.h> + +#ifdef RT_USING_USERSPACE + +#define USER_VADDR_TOP 0xC0000000UL +#define USER_HEAP_VEND 0xB0000000UL +#define USER_HEAP_VADDR 0x80000000UL +#define USER_STACK_VSTART 0x70000000UL +#define USER_STACK_VEND USER_HEAP_VADDR +#define LDSO_LOAD_VADDR 0x60000000UL +#define USER_VADDR_START 0x00100000UL +#define USER_LOAD_VADDR USER_VADDR_START + +#ifdef __cplusplus +extern "C" { +#endif + +rt_inline unsigned long rt_hw_ffz(unsigned long x) +{ + return __builtin_ffsl(~x) - 1; +} + +rt_inline void icache_invalid_all(void) +{ + asm volatile ("mcr p15, 0, r0, c7, c5, 0\ndsb\nisb":::"memory");//iciallu +} + +unsigned int arch_get_asid(struct rt_lwp *lwp); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif /*LWP_ARCH_H__*/ diff --git a/components/lwp/arch/arm/cortex-a/lwp_gcc.S b/components/lwp/arch/arm/cortex-a/lwp_gcc.S index 395974a2b7..30839e5970 100644 --- a/components/lwp/arch/arm/cortex-a/lwp_gcc.S +++ b/components/lwp/arch/arm/cortex-a/lwp_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2020, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -8,6 +8,8 @@ * 2018-12-10 Jesven first version */ +#include "rtconfig.h" + #define Mode_USR 0x10 #define Mode_FIQ 0x11 #define Mode_IRQ 0x12 @@ -27,22 +29,126 @@ .text /* - * void lwp_user_entry(args, text, data); + * void arch_start_umode(args, text, ustack, kstack); */ -.global lwp_user_entry -.type lwp_user_entry, % function -lwp_user_entry: +.global arch_start_umode +.type arch_start_umode, % function +arch_start_umode: mrs r9, cpsr bic r9, #0x1f orr r9, #Mode_USR cpsid i msr spsr, r9 + mov sp, r3 + mov r3, r2 ;/* user stack top */ /* set data address. */ - mov r9, r2 movs pc, r1 /* + * void arch_crt_start_umode(args, text, ustack, kstack); + */ +.global arch_crt_start_umode +.type arch_crt_start_umode, % function +arch_crt_start_umode: + cps #Mode_SYS + sub sp, r2, #16 + ldr r2, =lwp_thread_return + ldr r4, [r2] + str r4, [sp] + ldr r4, [r2, #4] + str r4, [sp, #4] + ldr r4, [r2, #8] + str r4, [sp, #8] + + mov r4, sp + mcr p15, 0, r4, c7, c11, 1 ;//dc cmvau + add r4, #4 + mcr p15, 0, r4, c7, c11, 1 ;//dc cmvau + add r4, #4 + mcr p15, 0, r4, c7, c11, 1 ;//dc cmvau + dsb + isb + mcr p15, 0, r4, c7, c5, 0 ;//iciallu + dsb + isb + + mov lr, sp + cps #Mode_SVC + + mrs r9, cpsr + bic r9, #0x1f + orr r9, #Mode_USR + cpsid i + msr spsr, r9 + mov sp, r3 + + /* set data address. */ + movs pc, r1 + +/* +void arch_set_thread_context(void *exit_addr, void *new_thread_stack, void *user_stack, void **thread_sp); +*/ +.global arch_set_thread_context +arch_set_thread_context: + sub r1, #(10 * 4 + 4 * 4) /* {r4 - r12, lr} , {r4, r5, spsr, u_pc} */ + stmfd r1!, {r0} + mov r12, #0 + stmfd r1!, {r12} + stmfd r1!, {r1 - r12} + stmfd r1!, {r12} /* new thread return value */ + mrs r12, cpsr + orr r12, #(1 << 7) /* disable irq */ + stmfd r1!, {r12} /* spsr */ + mov r12, #0 + stmfd r1!, {r12} /* now user lr is 0 */ + stmfd r1!, {r2} /* user sp */ +#ifdef RT_USING_FPU + stmfd r1!, {r12} /* not use fpu */ +#endif + str r1, [r3] + mov pc, lr + +.global arch_get_user_sp +arch_get_user_sp: + cps #Mode_SYS + mov r0, sp + cps #Mode_SVC + mov pc, lr + +.global sys_fork +.global sys_vfork +.global arch_fork_exit +sys_fork: +sys_vfork: + push {r4 - r12, lr} + bl _sys_fork +arch_fork_exit: + pop {r4 - r12, lr} + b arch_syscall_exit + +.global sys_clone +.global arch_clone_exit +sys_clone: + push {r4 - r12, lr} + bl _sys_clone +arch_clone_exit: + pop {r4 - r12, lr} + b arch_syscall_exit +/* +void lwp_exec_user(void *args, void *kernel_stack, void *user_entry) +*/ +.global lwp_exec_user +lwp_exec_user: + cpsid i + mov sp, r1 + mov lr, r2 + mov r2, #Mode_USR + msr spsr_cxsf, r2 + ldr r3, =0x80000000 + b arch_ret_to_user + +/* * void SVC_Handler(void); */ .global vector_swi @@ -51,20 +157,277 @@ vector_swi: push {lr} mrs lr, spsr push {r4, r5, lr} + cpsie i push {r0 - r3, r12} + + bl rt_thread_self + bl lwp_user_setting_save + + and r0, r7, #0xf000 + cmp r0, #0xe000 + beq arch_signal_quit + + cmp r0, #0xf000 + beq ret_from_user and r0, r7, #0xff bl lwp_get_sys_api cmp r0, #0 /* r0 = api */ mov lr, r0 + pop {r0 - r3, r12} - beq svc_exit + beq arch_syscall_exit blx lr -svc_exit: +.global arch_syscall_exit +arch_syscall_exit: cpsid i pop {r4, r5, lr} msr spsr_cxsf, lr pop {lr} + +.global arch_ret_to_user +arch_ret_to_user: + push {r0-r3, r12, lr} + bl lwp_check_debug + bl lwp_check_exit_request + cmp r0, #0 + beq 1f + mov r0, #0 + b sys_exit +1: + bl lwp_signal_check + cmp r0, #0 + pop {r0-r3, r12, lr} + bne user_do_signal + + push {r0} + ldr r0, =rt_dbg_ops + ldr r0, [r0] + cmp r0, #0 + pop {r0} + beq 2f + push {r0-r3, r12, lr} + mov r0, lr + bl dbg_attach_req + pop {r0-r3, r12, lr} +2: movs pc, lr + +#ifdef RT_USING_LWP +.global lwp_check_debug +lwp_check_debug: + ldr r0, =rt_dbg_ops + ldr r0, [r0] + cmp r0, #0 + bne 1f + bx lr +1: + push {lr} + bl dbg_check_suspend + cmp r0, #0 + beq lwp_check_debug_quit + + cps #Mode_SYS + sub sp, #8 + ldr r0, =lwp_debugreturn + ldr r1, [r0] + str r1, [sp] + ldr r1, [r0, #4] + str r1, [sp, #4] + + mov r1, sp + mcr p15, 0, r1, c7, c11, 1 ;//dc cmvau + add r1, #4 + mcr p15, 0, r1, c7, c11, 1 ;//dc cmvau + dsb + isb + mcr p15, 0, r0, c7, c5, 0 ;//iciallu + dsb + isb + + mov r0, sp /* lwp_debugreturn */ + cps #Mode_SVC + + mrs r1, spsr + push {r1} + mov r1, #Mode_USR + msr spsr_cxsf, r1 + movs pc, r0 +ret_from_user: + cps #Mode_SYS + add sp, #8 + cps #Mode_SVC + /* + pop {r0 - r3, r12} + pop {r4 - r6, lr} + */ + add sp, #(4*9) + pop {r4} + msr spsr_cxsf, r4 +lwp_check_debug_quit: + pop {pc} + +arch_signal_quit: + cpsid i + pop {r0 - r3, r12} + pop {r4, r5, lr} + pop {lr} + bl lwp_signal_restore + /* r0 is user_ctx : ori sp, pc, cpsr*/ + ldr r1, [r0] + ldr r2, [r0, #4] + ldr r3, [r0, #8] + msr spsr_cxsf, r3 + mov lr, r2 + cps #Mode_SYS + mov sp, r1 + pop {r0-r12, lr} + cps #Mode_SVC + b arch_ret_to_user + +user_do_signal: + mov r0, r0 + cps #Mode_SYS + push {r0-r12, lr} + + sub sp, #8 + ldr r0, =lwp_sigreturn + ldr r1, [r0] + str r1, [sp] + ldr r1, [r0, #4] + str r1, [sp, #4] + + mov r1, sp + mcr p15, 0, r1, c7, c11, 1 ;//dc cmvau + add r1, #4 + mcr p15, 0, r1, c7, c11, 1 ;//dc cmvau + dsb + isb + mcr p15, 0, r0, c7, c5, 0 ;//iciallu + dsb + isb + + mov r5, sp ;//if func is 0 + mov lr, sp + + add r0, sp, #8 /* lwp_sigreturn */ + cps #Mode_SVC + mov r1, lr + mrs r2, spsr + bl lwp_signal_backup + /* r0 is signal */ + mov r4, r0 + bl lwp_sighandler_get + mov lr, r0 + cmp lr, #0 + moveq lr, r5 + mov r0, r4 + movs pc, lr + +lwp_debugreturn: + mov r7, #0xf000 + svc #0 + +lwp_sigreturn: + mov r7, #0xe000 + svc #0 + +lwp_thread_return: + mov r0, #0 + mov r7, #0x01 + svc #0 +#endif + +.global check_vfp +check_vfp: +#ifdef RT_USING_FPU + vmrs r0, fpexc + ubfx r0, r0, #30, #1 +#else + mov r0, #0 +#endif + mov pc, lr + +.global get_vfp +get_vfp: +#ifdef RT_USING_FPU + vstmia r0!, {d0-d15} + vstmia r0!, {d16-d31} + vmrs r1, fpscr + str r1, [r0] +#endif + mov pc, lr + +.globl arch_get_tidr +arch_get_tidr: + mrc p15, 0, r0, c13, c0, 3 + bx lr + +.global arch_set_thread_area +arch_set_thread_area: +.globl arch_set_tidr +arch_set_tidr: + mcr p15, 0, r0, c13, c0, 3 + bx lr + +/* kuser suppurt */ + .macro kuser_pad, sym, size + .if (. - \sym) & 3 + .rept 4 - (. - \sym) & 3 + .byte 0 + .endr + .endif + .rept (\size - (. - \sym)) / 4 + .word 0xe7fddef1 + .endr + .endm + +.align 5 +.globl __kuser_helper_start +__kuser_helper_start: +__kuser_cmpxchg64: @ 0xffff0f60 + stmfd sp!, {r4, r5, r6, lr} + ldmia r0, {r4, r5} @ load old val + ldmia r1, {r6, lr} @ load new val +1: ldmia r2, {r0, r1} @ load current val + eors r3, r0, r4 @ compare with oldval (1) + eorseq r3, r1, r5 @ compare with oldval (2) +2: stmiaeq r2, {r6, lr} @ store newval if eq + rsbs r0, r3, #0 @ set return val and C flag + ldmfd sp!, {r4, r5, r6, pc} + + kuser_pad __kuser_cmpxchg64, 64 + +__kuser_memory_barrier: @ 0xffff0fa0 + dmb + mov pc, lr + + kuser_pad __kuser_memory_barrier, 32 + +__kuser_cmpxchg: @ 0xffff0fc0 +1: ldr r3, [r2] @ load current val + subs r3, r3, r0 @ compare with oldval +2: streq r1, [r2] @ store newval if eq + rsbs r0, r3, #0 @ set return val and C flag + mov pc, lr + +kuser_pad __kuser_cmpxchg, 32 + +__kuser_get_tls: @ 0xffff0fe0 + mrc p15, 0, r0, c13, c0, 3 @ 0xffff0fe8 hardware TLS code + mov pc, lr + ldr r0, [pc, #(16 - 8)] @ read TLS, set in kuser_get_tls_init + + kuser_pad __kuser_get_tls, 16 + + .rep 3 + .word 0 @ 0xffff0ff0 software TLS value, then + .endr @ pad up to __kuser_helper_version + +__kuser_helper_version: @ 0xffff0ffc + .word ((__kuser_helper_end - __kuser_helper_start) >> 5) + + .globl __kuser_helper_end +__kuser_helper_end: diff --git a/components/lwp/arch/arm/cortex-a9/lwp_gcc.S b/components/lwp/arch/arm/cortex-a9/lwp_gcc.S deleted file mode 100644 index 93e88f7c97..0000000000 --- a/components/lwp/arch/arm/cortex-a9/lwp_gcc.S +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2018-12-10 Jesven first version - */ - -#define Mode_USR 0x10 -#define Mode_FIQ 0x11 -#define Mode_IRQ 0x12 -#define Mode_SVC 0x13 -#define Mode_MON 0x16 -#define Mode_ABT 0x17 -#define Mode_UDF 0x1B -#define Mode_SYS 0x1F - -#define A_Bit 0x100 -#define I_Bit 0x80 @; when I bit is set, IRQ is disabled -#define F_Bit 0x40 @; when F bit is set, FIQ is disabled -#define T_Bit 0x20 - -.cpu cortex-a9 -.syntax unified -.text - -/* - * void lwp_user_entry(args, text, data); - */ -.global lwp_user_entry -.type lwp_user_entry, % function -lwp_user_entry: - mrs r9, cpsr - bic r9, #0x1f - orr r9, #Mode_USR - cpsid i - msr spsr, r9 - - /* set data address. */ - mov r9, r2 - movs pc, r1 - -/* - * void vector_swi(void); - */ -.global vector_swi -.type vector_swi, % function -vector_swi: - push {lr} - mrs lr, spsr - push {r4, r5, lr} - cpsie i - - push {r0 - r3, r12} - and r0, r7, #0xff - bl lwp_get_sys_api - cmp r0, #0 /* r0 = api */ - mov lr, r0 - pop {r0 - r3, r12} - beq svc_exit - blx lr - -svc_exit: - cpsid i - pop {r4, r5, lr} - msr spsr_cxsf, lr - pop {lr} - movs pc, lr diff --git a/components/lwp/arch/arm/cortex-m3/lwp_gcc.S b/components/lwp/arch/arm/cortex-m3/lwp_gcc.S deleted file mode 100644 index 846b06bb26..0000000000 --- a/components/lwp/arch/arm/cortex-m3/lwp_gcc.S +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2018-10-30 heyuanjie first version - */ - -.cpu cortex-m3 -.syntax unified -.thumb -.text - -/* - * void* lwp_get_sys_api(rt_uint32_t number); - */ -.global lwp_get_sys_api -.global lwp_get_kernel_sp -.global lwp_set_kernel_sp - - -/* - * void lwp_user_entry(args, text, data); - */ -.global lwp_user_entry -.type lwp_user_entry, % function -lwp_user_entry: - PUSH {R0-R3} @; push text&data addr. - - MOV R0, SP @; v1 = SP - BL lwp_set_kernel_sp @; lwp_set_kernel_sp(v1) - - @; set CPU to user-thread mode. - MRS R2, CONTROL - ORR R2, R2, #0x03 @; use PSP, user-thread mode. - MSR CONTROL, R2 - - POP {R0-R3} @; pop app address to R1. - @; set data address. - MOV R9, R2 - - @; run app, only Thumb-mode. - ORR R1, R1, #0x01 - BX R1 - -/* - * void SVC_Handler(void); - */ -.global SVC_Handler -.type SVC_Handler, % function -SVC_Handler: - PUSH {LR} - - @; get user SP. - TST LR, #0x4 - ITE EQ - MRSEQ R1, MSP - MRSNE R1, PSP - PUSH {R1} @; push app SP. - - @; get SVC number. - mov R0, R7 - - @; get kernel system API - BL lwp_get_sys_api - - PUSH {R0} @; push api - - @; get kernel SP to R0. - BL lwp_get_kernel_sp - - POP {R2} @; pop api to R2. - POP {R1} @; pop app SP to R1. - - stmfd r0!, {r1} @; save app SP to kernel SP - - @;push app parm5~6 to kernel SP - STMFD R0!, {R4 - R5} - @; copy R1(app SP) to R0(kernel SP). - push {r8-r11} - LDMFD R1, {R4 - R11} @; pop exception_stack_frame to r4 - r11 register - STMFD R0!, {R4 - R11} @; push exception_stack_frame to server SP. - pop {r8-r11} - - LDR R3, =svc_exit - STR R3, [R0, #20] @; update LR - STR R2, [R0, #24] @; update api to PC - MSR PSP, R0 @; update SP, API is executed with kernel SP - - @; set to thread-privilege mode. - MRS R3, CONTROL - BIC R3, R3, #0x01 - ORR R3, R3, #0x02 - MSR CONTROL, R3 - - POP {LR} @; 0xFFFFFFED - ORR LR, LR, #0x10 - BX LR -/* -* void svc_exit(void); -*/ -.global svc_exit -.type svc_exit, % function -svc_exit: - @; get user SP. - PUSH {R0} @; push result to SP. - BL lwp_get_kernel_sp - ldr r3, [r0, #-4] - pop {r0} - - ldr lr, [r3, #20] - ldr r1, [r3, #24] @; load pc - add r3, #32 @; exception_stack_frame size - MSR PSP, R3 @; restore app stack pointer - @; restore to PSP & thread-unprivilege mode. - MRS R2, CONTROL - ORR R2, R2, #0x03 - MSR CONTROL, R2 - - @; return to lwp. - ORR R1, R1, #0x01 @; only Thumb-mode. - BX R1 @; return to user app. diff --git a/components/lwp/arch/arm/cortex-m3/lwp_iar.S b/components/lwp/arch/arm/cortex-m3/lwp_iar.S deleted file mode 100644 index a218569375..0000000000 --- a/components/lwp/arch/arm/cortex-m3/lwp_iar.S +++ /dev/null @@ -1,123 +0,0 @@ -;/* -; * Copyright (c) 2006-2018, RT-Thread Development Team -; * -; * SPDX-License-Identifier: Apache-2.0 -; * -; * Change Logs: -; * Date Author Notes -; * 2018-10-30 heyuanjie first version -; */ - - SECTION .text:CODE(2) - THUMB - REQUIRE8 - PRESERVE8 - -;/* -; * void* lwp_get_sys_api(rt_uint32_t number); -; */ - IMPORT lwp_get_sys_api - IMPORT lwp_get_kernel_sp - IMPORT lwp_set_kernel_sp - -;/* -; * void lwp_user_entry(args, text, data); -; */ - EXPORT lwp_user_entry -lwp_user_entry: - PUSH {R0-R3} ; push text&data addr. - - MOV R0, SP ; v1 = SP - BL lwp_set_kernel_sp ; lwp_set_kernel_sp(v1) - - ; set CPU to user-thread mode. - MRS R2, CONTROL - ORR R2, R2, #0x03 ; use PSP, user-thread mode. - MSR CONTROL, R2 - - POP {R0-R3} ; pop app address to R1. - ; set data address. - MOV R9, R2 - - ; run app, only Thumb-mode. - ORR R1, R1, #0x01 - BX R1 - -;/* -; * void SVC_Handler(void); -; */ - EXPORT SVC_Handler -SVC_Handler: - PUSH {LR} - - ; get user SP. - TST LR, #0x4 - ITE EQ - MRSEQ R1, MSP - MRSNE R1, PSP - PUSH {R1} ; push app SP. - - ; get SVC number. - mov R0, R7 - - ; get kernel system API - BL lwp_get_sys_api - - PUSH {R0} ; push api - - ; get kernel SP to R0. - BL lwp_get_kernel_sp - - POP {R2} ; pop api to R2. - POP {R1} ; pop app SP to R1. - - stmfd r0!, {r1} ; save app SP to kernel SP - - ;push app parm5~6 to kernel SP - STMFD R0!, {R4 - R5} - ; copy R1(app SP) to R0(kernel SP). - push {r8-r11} - LDMFD R1, {R4 - R11} ; pop exception_stack_frame to r4 - r11 register - STMFD R0!, {R4 - R11} ; push exception_stack_frame to server SP. - pop {r8-r11} - - LDR R3, =svc_exit - STR R3, [R0, #20] ; update LR - STR R2, [R0, #24] ; update api to PC - MSR PSP, R0 ; update SP, API is executed with kernel SP - - ; set to thread-privilege mode. - MRS R3, CONTROL - BIC R3, R3, #0x01 - ORR R3, R3, #0x02 - MSR CONTROL, R3 - - POP {LR} ; 0xFFFFFFED - ORR LR, LR, #0x10 - BX LR - -;/* -; * void svc_exit(void); -; */ - EXPORT svc_exit -svc_exit: - ; get user SP. - PUSH {R0} ; push result to SP. - BL lwp_get_kernel_sp - ldr r3, [r0, #-4] - pop {r0} - - ldr lr, [r3, #20] - ldr r1, [r3, #24] ; load pc - add r3, r3, #32 ; exception_stack_frame size - MSR PSP, R3 ; restore app stack pointer - ; restore to PSP & thread-unprivilege mode. - MRS R2, CONTROL - ORR R2, R2, #0x03 - MSR CONTROL, R2 - - ; return to lwp. - ORR R1, R1, #0x01 ; only Thumb-mode. - BX R1 ; return to user app. - - END diff --git a/components/lwp/arch/arm/cortex-m3/lwp_rvds.S b/components/lwp/arch/arm/cortex-m3/lwp_rvds.S deleted file mode 100644 index 246751a847..0000000000 --- a/components/lwp/arch/arm/cortex-m3/lwp_rvds.S +++ /dev/null @@ -1,135 +0,0 @@ -;/* -; * Copyright (c) 2006-2018, RT-Thread Development Team -; * -; * SPDX-License-Identifier: Apache-2.0 -; * -; * Change Logs: -; * Date Author Notes -; * 2018-10-30 heyuanjie first version -; */ - - AREA |.text|, CODE, READONLY, ALIGN=2 - THUMB - REQUIRE8 - PRESERVE8 - -;/* -; * void* lwp_get_sys_api(rt_uint32_t number); -; */ - IMPORT lwp_get_sys_api - IMPORT lwp_get_kernel_sp - IMPORT lwp_set_kernel_sp - -;/* -; * void lwp_user_entry(args, text, data); -; */ -lwp_user_entry PROC - EXPORT lwp_user_entry - - PUSH {R0-R3} ; push text&data addr. - - MOV R0, SP ; v1 = SP - BL lwp_set_kernel_sp ; lwp_set_kernel_sp(v1) - - ; set CPU to user-thread mode. - MRS R2, CONTROL - ORR R2, R2, #0x03 ; use PSP, user-thread mode. - MSR CONTROL, R2 - - POP {R0-R3} ; pop app address to R1. - ; set data address. - MOV R9, R2 - - ; run app, only Thumb-mode. - ORR R1, R1, #0x01 - BX R1 - - ; never reach here! - ENDP - -;/* -; * void SVC_Handler(void); -; */ -SVC_Handler PROC - EXPORT SVC_Handler - - PUSH {LR} - - ; get user SP. - TST LR, #0x4 - ITE EQ - MRSEQ R1, MSP - MRSNE R1, PSP - PUSH {R1} ; push app SP. - - ; get SVC number. - mov R0, R7 - - ; get kernel system API - BL lwp_get_sys_api - - PUSH {R0} ; push api - - ; get kernel SP to R0. - BL lwp_get_kernel_sp - - POP {R2} ; pop api to R2. - POP {R1} ; pop app SP to R1. - - stmfd r0!, {r1} ; save app SP to kernel SP - - ;push app parm5~6 to kernel SP - STMFD R0!, {R4 - R5} - ; copy R1(app SP) to R0(kernel SP). - push {r8-r11} - LDMFD R1, {R4 - R11} ; pop exception_stack_frame to r4 - r11 register - STMFD R0!, {R4 - R11} ; push exception_stack_frame to server SP. - pop {r8-r11} - - LDR R3, =svc_exit - STR R3, [R0, #20] ; update LR - STR R2, [R0, #24] ; update api to PC - MSR PSP, R0 ; update SP, API is executed with kernel SP - - ; set to thread-privilege mode. - MRS R3, CONTROL - BIC R3, R3, #0x01 - ORR R3, R3, #0x02 - MSR CONTROL, R3 - - POP {LR} ; 0xFFFFFFED - ORR LR, LR, #0x10 - BX LR - - ENDP - -;/* -; * void svc_exit(void); -; */ -svc_exit PROC - EXPORT svc_exit - - ; get user SP. - PUSH {R0} ; push result to SP. - BL lwp_get_kernel_sp - ldr r3, [r0, #-4] - pop {r0} - - ldr lr, [r3, #20] - ldr r1, [r3, #24] ; load pc - add r3, #32 ; exception_stack_frame size - MSR PSP, R3 ; restore app stack pointer - ; restore to PSP & thread-unprivilege mode. - MRS R2, CONTROL - ORR R2, R2, #0x03 - MSR CONTROL, R2 - - ; return to lwp. - ORR R1, R1, #0x01 ; only Thumb-mode. - BX R1 ; return to user app. - - ENDP - - ALIGN - - END diff --git a/components/lwp/arch/arm/cortex-m4/lwp_gcc.S b/components/lwp/arch/arm/cortex-m4/lwp_gcc.S deleted file mode 100644 index e71dbb82c9..0000000000 --- a/components/lwp/arch/arm/cortex-m4/lwp_gcc.S +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2018-10-30 heyuanjie first version - */ - -.cpu cortex-m4 -.syntax unified -.thumb -.text - -/* - * void* lwp_get_sys_api(rt_uint32_t number); - */ -.global lwp_get_sys_api -.global lwp_get_kernel_sp -.global lwp_set_kernel_sp - - -/* - * void lwp_user_entry(args, text, data); - */ -.global lwp_user_entry -.type lwp_user_entry, % function -lwp_user_entry: - PUSH {R0-R3} @; push text&data addr. - - MOV R0, SP @; v1 = SP - BL lwp_set_kernel_sp @; lwp_set_kernel_sp(v1) - - @; set CPU to user-thread mode. - MRS R2, CONTROL - ORR R2, R2, #0x03 @; use PSP, user-thread mode. - MSR CONTROL, R2 - - POP {R0-R3} @; pop app address to R1. - @; set data address. - MOV R9, R2 - - @; run app, only Thumb-mode. - ORR R1, R1, #0x01 - BX R1 - -/* - * void SVC_Handler(void); - */ -.global SVC_Handler -.type SVC_Handler, % function -SVC_Handler: - PUSH {LR} - - @; get user SP. - TST LR, #0x4 - ITE EQ - MRSEQ R1, MSP - MRSNE R1, PSP - PUSH {R1} @; push app SP. - - @; get SVC number. - mov R0, R7 - - @; get kernel system API - BL lwp_get_sys_api - - PUSH {R0} @; push api - - @; get kernel SP to R0. - BL lwp_get_kernel_sp - - POP {R2} @; pop api to R2. - POP {R1} @; pop app SP to R1. - - stmfd r0!, {r1} @; save app SP to kernel SP - - @;push app parm5~6 to kernel SP - STMFD R0!, {R4 - R5} - @; copy R1(app SP) to R0(kernel SP). - push {r8-r11} - LDMFD R1, {R4 - R11} @; pop exception_stack_frame to r4 - r11 register - STMFD R0!, {R4 - R11} @; push exception_stack_frame to server SP. - pop {r8-r11} - - LDR R3, =svc_exit - STR R3, [R0, #20] @; update LR - STR R2, [R0, #24] @; update api to PC - MSR PSP, R0 @; update SP, API is executed with kernel SP - - @; set to thread-privilege mode. - MRS R3, CONTROL - BIC R3, R3, #0x01 - ORR R3, R3, #0x02 - MSR CONTROL, R3 - - POP {LR} @; 0xFFFFFFED - ORR LR, LR, #0x10 - BX LR -/* -* void svc_exit(void); -*/ -.global svc_exit -.type svc_exit, % function -svc_exit: - @; get user SP. - PUSH {R0} @; push result to SP. - BL lwp_get_kernel_sp - ldr r3, [r0, #-4] - pop {r0} - - ldr lr, [r3, #20] - ldr r1, [r3, #24] @; load pc - add r3, #32 @; exception_stack_frame size - MSR PSP, R3 @; restore app stack pointer - @; restore to PSP & thread-unprivilege mode. - MRS R2, CONTROL - ORR R2, R2, #0x03 - MSR CONTROL, R2 - - @; return to lwp. - ORR R1, R1, #0x01 @; only Thumb-mode. - BX R1 @; return to user app. diff --git a/components/lwp/arch/arm/cortex-m4/lwp_iar.S b/components/lwp/arch/arm/cortex-m4/lwp_iar.S deleted file mode 100644 index a218569375..0000000000 --- a/components/lwp/arch/arm/cortex-m4/lwp_iar.S +++ /dev/null @@ -1,123 +0,0 @@ -;/* -; * Copyright (c) 2006-2018, RT-Thread Development Team -; * -; * SPDX-License-Identifier: Apache-2.0 -; * -; * Change Logs: -; * Date Author Notes -; * 2018-10-30 heyuanjie first version -; */ - - SECTION .text:CODE(2) - THUMB - REQUIRE8 - PRESERVE8 - -;/* -; * void* lwp_get_sys_api(rt_uint32_t number); -; */ - IMPORT lwp_get_sys_api - IMPORT lwp_get_kernel_sp - IMPORT lwp_set_kernel_sp - -;/* -; * void lwp_user_entry(args, text, data); -; */ - EXPORT lwp_user_entry -lwp_user_entry: - PUSH {R0-R3} ; push text&data addr. - - MOV R0, SP ; v1 = SP - BL lwp_set_kernel_sp ; lwp_set_kernel_sp(v1) - - ; set CPU to user-thread mode. - MRS R2, CONTROL - ORR R2, R2, #0x03 ; use PSP, user-thread mode. - MSR CONTROL, R2 - - POP {R0-R3} ; pop app address to R1. - ; set data address. - MOV R9, R2 - - ; run app, only Thumb-mode. - ORR R1, R1, #0x01 - BX R1 - -;/* -; * void SVC_Handler(void); -; */ - EXPORT SVC_Handler -SVC_Handler: - PUSH {LR} - - ; get user SP. - TST LR, #0x4 - ITE EQ - MRSEQ R1, MSP - MRSNE R1, PSP - PUSH {R1} ; push app SP. - - ; get SVC number. - mov R0, R7 - - ; get kernel system API - BL lwp_get_sys_api - - PUSH {R0} ; push api - - ; get kernel SP to R0. - BL lwp_get_kernel_sp - - POP {R2} ; pop api to R2. - POP {R1} ; pop app SP to R1. - - stmfd r0!, {r1} ; save app SP to kernel SP - - ;push app parm5~6 to kernel SP - STMFD R0!, {R4 - R5} - ; copy R1(app SP) to R0(kernel SP). - push {r8-r11} - LDMFD R1, {R4 - R11} ; pop exception_stack_frame to r4 - r11 register - STMFD R0!, {R4 - R11} ; push exception_stack_frame to server SP. - pop {r8-r11} - - LDR R3, =svc_exit - STR R3, [R0, #20] ; update LR - STR R2, [R0, #24] ; update api to PC - MSR PSP, R0 ; update SP, API is executed with kernel SP - - ; set to thread-privilege mode. - MRS R3, CONTROL - BIC R3, R3, #0x01 - ORR R3, R3, #0x02 - MSR CONTROL, R3 - - POP {LR} ; 0xFFFFFFED - ORR LR, LR, #0x10 - BX LR - -;/* -; * void svc_exit(void); -; */ - EXPORT svc_exit -svc_exit: - ; get user SP. - PUSH {R0} ; push result to SP. - BL lwp_get_kernel_sp - ldr r3, [r0, #-4] - pop {r0} - - ldr lr, [r3, #20] - ldr r1, [r3, #24] ; load pc - add r3, r3, #32 ; exception_stack_frame size - MSR PSP, R3 ; restore app stack pointer - ; restore to PSP & thread-unprivilege mode. - MRS R2, CONTROL - ORR R2, R2, #0x03 - MSR CONTROL, R2 - - ; return to lwp. - ORR R1, R1, #0x01 ; only Thumb-mode. - BX R1 ; return to user app. - - END diff --git a/components/lwp/arch/arm/cortex-m4/lwp_rvds.S b/components/lwp/arch/arm/cortex-m4/lwp_rvds.S deleted file mode 100644 index 246751a847..0000000000 --- a/components/lwp/arch/arm/cortex-m4/lwp_rvds.S +++ /dev/null @@ -1,135 +0,0 @@ -;/* -; * Copyright (c) 2006-2018, RT-Thread Development Team -; * -; * SPDX-License-Identifier: Apache-2.0 -; * -; * Change Logs: -; * Date Author Notes -; * 2018-10-30 heyuanjie first version -; */ - - AREA |.text|, CODE, READONLY, ALIGN=2 - THUMB - REQUIRE8 - PRESERVE8 - -;/* -; * void* lwp_get_sys_api(rt_uint32_t number); -; */ - IMPORT lwp_get_sys_api - IMPORT lwp_get_kernel_sp - IMPORT lwp_set_kernel_sp - -;/* -; * void lwp_user_entry(args, text, data); -; */ -lwp_user_entry PROC - EXPORT lwp_user_entry - - PUSH {R0-R3} ; push text&data addr. - - MOV R0, SP ; v1 = SP - BL lwp_set_kernel_sp ; lwp_set_kernel_sp(v1) - - ; set CPU to user-thread mode. - MRS R2, CONTROL - ORR R2, R2, #0x03 ; use PSP, user-thread mode. - MSR CONTROL, R2 - - POP {R0-R3} ; pop app address to R1. - ; set data address. - MOV R9, R2 - - ; run app, only Thumb-mode. - ORR R1, R1, #0x01 - BX R1 - - ; never reach here! - ENDP - -;/* -; * void SVC_Handler(void); -; */ -SVC_Handler PROC - EXPORT SVC_Handler - - PUSH {LR} - - ; get user SP. - TST LR, #0x4 - ITE EQ - MRSEQ R1, MSP - MRSNE R1, PSP - PUSH {R1} ; push app SP. - - ; get SVC number. - mov R0, R7 - - ; get kernel system API - BL lwp_get_sys_api - - PUSH {R0} ; push api - - ; get kernel SP to R0. - BL lwp_get_kernel_sp - - POP {R2} ; pop api to R2. - POP {R1} ; pop app SP to R1. - - stmfd r0!, {r1} ; save app SP to kernel SP - - ;push app parm5~6 to kernel SP - STMFD R0!, {R4 - R5} - ; copy R1(app SP) to R0(kernel SP). - push {r8-r11} - LDMFD R1, {R4 - R11} ; pop exception_stack_frame to r4 - r11 register - STMFD R0!, {R4 - R11} ; push exception_stack_frame to server SP. - pop {r8-r11} - - LDR R3, =svc_exit - STR R3, [R0, #20] ; update LR - STR R2, [R0, #24] ; update api to PC - MSR PSP, R0 ; update SP, API is executed with kernel SP - - ; set to thread-privilege mode. - MRS R3, CONTROL - BIC R3, R3, #0x01 - ORR R3, R3, #0x02 - MSR CONTROL, R3 - - POP {LR} ; 0xFFFFFFED - ORR LR, LR, #0x10 - BX LR - - ENDP - -;/* -; * void svc_exit(void); -; */ -svc_exit PROC - EXPORT svc_exit - - ; get user SP. - PUSH {R0} ; push result to SP. - BL lwp_get_kernel_sp - ldr r3, [r0, #-4] - pop {r0} - - ldr lr, [r3, #20] - ldr r1, [r3, #24] ; load pc - add r3, #32 ; exception_stack_frame size - MSR PSP, R3 ; restore app stack pointer - ; restore to PSP & thread-unprivilege mode. - MRS R2, CONTROL - ORR R2, R2, #0x03 - MSR CONTROL, R2 - - ; return to lwp. - ORR R1, R1, #0x01 ; only Thumb-mode. - BX R1 ; return to user app. - - ENDP - - ALIGN - - END diff --git a/components/lwp/arch/arm/cortex-m7/lwp_gcc.S b/components/lwp/arch/arm/cortex-m7/lwp_gcc.S deleted file mode 100644 index 848c592919..0000000000 --- a/components/lwp/arch/arm/cortex-m7/lwp_gcc.S +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2018-10-30 heyuanjie first version - */ - -.cpu cortex-m7 -.syntax unified -.thumb -.text - -/* - * void* lwp_get_sys_api(rt_uint32_t number); - */ -.global lwp_get_sys_api -.global lwp_get_kernel_sp -.global lwp_set_kernel_sp - - -/* - * void lwp_user_entry(args, text, data); - */ -.global lwp_user_entry -.type lwp_user_entry, % function -lwp_user_entry: - PUSH {R0-R3} @; push text&data addr. - - MOV R0, SP @; v1 = SP - BL lwp_set_kernel_sp @; lwp_set_kernel_sp(v1) - - @; set CPU to user-thread mode. - MRS R2, CONTROL - ORR R2, R2, #0x03 @; use PSP, user-thread mode. - MSR CONTROL, R2 - - POP {R0-R3} @; pop app address to R1. - @; set data address. - MOV R9, R2 - - @; run app, only Thumb-mode. - ORR R1, R1, #0x01 - BX R1 - -/* - * void SVC_Handler(void); - */ -.global SVC_Handler -.type SVC_Handler, % function -SVC_Handler: - PUSH {LR} - - @; get user SP. - TST LR, #0x4 - ITE EQ - MRSEQ R1, MSP - MRSNE R1, PSP - PUSH {R1} @; push app SP. - - @; get SVC number. - mov R0, R7 - - @; get kernel system API - BL lwp_get_sys_api - - PUSH {R0} @; push api - - @; get kernel SP to R0. - BL lwp_get_kernel_sp - - POP {R2} @; pop api to R2. - POP {R1} @; pop app SP to R1. - - stmfd r0!, {r1} @; save app SP to kernel SP - - @;push app parm5~6 to kernel SP - STMFD R0!, {R4 - R5} - @; copy R1(app SP) to R0(kernel SP). - push {r8-r11} - LDMFD R1, {R4 - R11} @; pop exception_stack_frame to r4 - r11 register - STMFD R0!, {R4 - R11} @; push exception_stack_frame to server SP. - pop {r8-r11} - - LDR R3, =svc_exit - STR R3, [R0, #20] @; update LR - STR R2, [R0, #24] @; update api to PC - MSR PSP, R0 @; update SP, API is executed with kernel SP - - @; set to thread-privilege mode. - MRS R3, CONTROL - BIC R3, R3, #0x01 - ORR R3, R3, #0x02 - MSR CONTROL, R3 - - POP {LR} @; 0xFFFFFFED - ORR LR, LR, #0x10 - BX LR -/* -* void svc_exit(void); -*/ -.global svc_exit -.type svc_exit, % function -svc_exit: - @; get user SP. - PUSH {R0} @; push result to SP. - BL lwp_get_kernel_sp - ldr r3, [r0, #-4] - pop {r0} - - ldr lr, [r3, #20] - ldr r1, [r3, #24] @; load pc - add r3, #32 @; exception_stack_frame size - MSR PSP, R3 @; restore app stack pointer - @; restore to PSP & thread-unprivilege mode. - MRS R2, CONTROL - ORR R2, R2, #0x03 - MSR CONTROL, R2 - - @; return to lwp. - ORR R1, R1, #0x01 @; only Thumb-mode. - BX R1 @; return to user app. diff --git a/components/lwp/arch/arm/cortex-m7/lwp_iar.S b/components/lwp/arch/arm/cortex-m7/lwp_iar.S deleted file mode 100644 index a218569375..0000000000 --- a/components/lwp/arch/arm/cortex-m7/lwp_iar.S +++ /dev/null @@ -1,123 +0,0 @@ -;/* -; * Copyright (c) 2006-2018, RT-Thread Development Team -; * -; * SPDX-License-Identifier: Apache-2.0 -; * -; * Change Logs: -; * Date Author Notes -; * 2018-10-30 heyuanjie first version -; */ - - SECTION .text:CODE(2) - THUMB - REQUIRE8 - PRESERVE8 - -;/* -; * void* lwp_get_sys_api(rt_uint32_t number); -; */ - IMPORT lwp_get_sys_api - IMPORT lwp_get_kernel_sp - IMPORT lwp_set_kernel_sp - -;/* -; * void lwp_user_entry(args, text, data); -; */ - EXPORT lwp_user_entry -lwp_user_entry: - PUSH {R0-R3} ; push text&data addr. - - MOV R0, SP ; v1 = SP - BL lwp_set_kernel_sp ; lwp_set_kernel_sp(v1) - - ; set CPU to user-thread mode. - MRS R2, CONTROL - ORR R2, R2, #0x03 ; use PSP, user-thread mode. - MSR CONTROL, R2 - - POP {R0-R3} ; pop app address to R1. - ; set data address. - MOV R9, R2 - - ; run app, only Thumb-mode. - ORR R1, R1, #0x01 - BX R1 - -;/* -; * void SVC_Handler(void); -; */ - EXPORT SVC_Handler -SVC_Handler: - PUSH {LR} - - ; get user SP. - TST LR, #0x4 - ITE EQ - MRSEQ R1, MSP - MRSNE R1, PSP - PUSH {R1} ; push app SP. - - ; get SVC number. - mov R0, R7 - - ; get kernel system API - BL lwp_get_sys_api - - PUSH {R0} ; push api - - ; get kernel SP to R0. - BL lwp_get_kernel_sp - - POP {R2} ; pop api to R2. - POP {R1} ; pop app SP to R1. - - stmfd r0!, {r1} ; save app SP to kernel SP - - ;push app parm5~6 to kernel SP - STMFD R0!, {R4 - R5} - ; copy R1(app SP) to R0(kernel SP). - push {r8-r11} - LDMFD R1, {R4 - R11} ; pop exception_stack_frame to r4 - r11 register - STMFD R0!, {R4 - R11} ; push exception_stack_frame to server SP. - pop {r8-r11} - - LDR R3, =svc_exit - STR R3, [R0, #20] ; update LR - STR R2, [R0, #24] ; update api to PC - MSR PSP, R0 ; update SP, API is executed with kernel SP - - ; set to thread-privilege mode. - MRS R3, CONTROL - BIC R3, R3, #0x01 - ORR R3, R3, #0x02 - MSR CONTROL, R3 - - POP {LR} ; 0xFFFFFFED - ORR LR, LR, #0x10 - BX LR - -;/* -; * void svc_exit(void); -; */ - EXPORT svc_exit -svc_exit: - ; get user SP. - PUSH {R0} ; push result to SP. - BL lwp_get_kernel_sp - ldr r3, [r0, #-4] - pop {r0} - - ldr lr, [r3, #20] - ldr r1, [r3, #24] ; load pc - add r3, r3, #32 ; exception_stack_frame size - MSR PSP, R3 ; restore app stack pointer - ; restore to PSP & thread-unprivilege mode. - MRS R2, CONTROL - ORR R2, R2, #0x03 - MSR CONTROL, R2 - - ; return to lwp. - ORR R1, R1, #0x01 ; only Thumb-mode. - BX R1 ; return to user app. - - END diff --git a/components/lwp/arch/arm/cortex-m7/lwp_rvds.S b/components/lwp/arch/arm/cortex-m7/lwp_rvds.S deleted file mode 100644 index 246751a847..0000000000 --- a/components/lwp/arch/arm/cortex-m7/lwp_rvds.S +++ /dev/null @@ -1,135 +0,0 @@ -;/* -; * Copyright (c) 2006-2018, RT-Thread Development Team -; * -; * SPDX-License-Identifier: Apache-2.0 -; * -; * Change Logs: -; * Date Author Notes -; * 2018-10-30 heyuanjie first version -; */ - - AREA |.text|, CODE, READONLY, ALIGN=2 - THUMB - REQUIRE8 - PRESERVE8 - -;/* -; * void* lwp_get_sys_api(rt_uint32_t number); -; */ - IMPORT lwp_get_sys_api - IMPORT lwp_get_kernel_sp - IMPORT lwp_set_kernel_sp - -;/* -; * void lwp_user_entry(args, text, data); -; */ -lwp_user_entry PROC - EXPORT lwp_user_entry - - PUSH {R0-R3} ; push text&data addr. - - MOV R0, SP ; v1 = SP - BL lwp_set_kernel_sp ; lwp_set_kernel_sp(v1) - - ; set CPU to user-thread mode. - MRS R2, CONTROL - ORR R2, R2, #0x03 ; use PSP, user-thread mode. - MSR CONTROL, R2 - - POP {R0-R3} ; pop app address to R1. - ; set data address. - MOV R9, R2 - - ; run app, only Thumb-mode. - ORR R1, R1, #0x01 - BX R1 - - ; never reach here! - ENDP - -;/* -; * void SVC_Handler(void); -; */ -SVC_Handler PROC - EXPORT SVC_Handler - - PUSH {LR} - - ; get user SP. - TST LR, #0x4 - ITE EQ - MRSEQ R1, MSP - MRSNE R1, PSP - PUSH {R1} ; push app SP. - - ; get SVC number. - mov R0, R7 - - ; get kernel system API - BL lwp_get_sys_api - - PUSH {R0} ; push api - - ; get kernel SP to R0. - BL lwp_get_kernel_sp - - POP {R2} ; pop api to R2. - POP {R1} ; pop app SP to R1. - - stmfd r0!, {r1} ; save app SP to kernel SP - - ;push app parm5~6 to kernel SP - STMFD R0!, {R4 - R5} - ; copy R1(app SP) to R0(kernel SP). - push {r8-r11} - LDMFD R1, {R4 - R11} ; pop exception_stack_frame to r4 - r11 register - STMFD R0!, {R4 - R11} ; push exception_stack_frame to server SP. - pop {r8-r11} - - LDR R3, =svc_exit - STR R3, [R0, #20] ; update LR - STR R2, [R0, #24] ; update api to PC - MSR PSP, R0 ; update SP, API is executed with kernel SP - - ; set to thread-privilege mode. - MRS R3, CONTROL - BIC R3, R3, #0x01 - ORR R3, R3, #0x02 - MSR CONTROL, R3 - - POP {LR} ; 0xFFFFFFED - ORR LR, LR, #0x10 - BX LR - - ENDP - -;/* -; * void svc_exit(void); -; */ -svc_exit PROC - EXPORT svc_exit - - ; get user SP. - PUSH {R0} ; push result to SP. - BL lwp_get_kernel_sp - ldr r3, [r0, #-4] - pop {r0} - - ldr lr, [r3, #20] - ldr r1, [r3, #24] ; load pc - add r3, #32 ; exception_stack_frame size - MSR PSP, R3 ; restore app stack pointer - ; restore to PSP & thread-unprivilege mode. - MRS R2, CONTROL - ORR R2, R2, #0x03 - MSR CONTROL, R2 - - ; return to lwp. - ORR R1, R1, #0x01 ; only Thumb-mode. - BX R1 ; return to user app. - - ENDP - - ALIGN - - END diff --git a/components/lwp/arch/risc-v/rv64/SConscript b/components/lwp/arch/risc-v/rv64/SConscript new file mode 100644 index 0000000000..e98e7650b1 --- /dev/null +++ b/components/lwp/arch/risc-v/rv64/SConscript @@ -0,0 +1,11 @@ +# RT-Thread building script for component + +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') + Glob('*.S') +CPPPATH = [cwd] + +group = DefineGroup('lwp-riscv', src, depend = ['RT_USING_LWP'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/lwp/arch/risc-v/rv64/lwp_arch.c b/components/lwp/arch/risc-v/rv64/lwp_arch.c new file mode 100644 index 0000000000..a1e0b8f31a --- /dev/null +++ b/components/lwp/arch/risc-v/rv64/lwp_arch.c @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-11-18 Jesven first version + * 2021-02-03 lizhirui port to riscv64 + * 2021-02-06 lizhirui add thread filter + * 2021-02-19 lizhirui port to new version of rt-smart + * 2021-03-02 lizhirui add a auxillary function for interrupt + * 2021-03-04 lizhirui delete thread filter + * 2021-03-04 lizhirui modify for new version of rt-smart + * 2021-11-22 JasonHu add lwp_set_thread_context + * 2021-11-30 JasonHu add clone/fork support + */ + +#include <rthw.h> +#include <stddef.h> + +#ifdef RT_USING_USERSPACE + +#include <mmu.h> +#include <page.h> +#include <lwp_mm_area.h> +#include <lwp_user_mm.h> +#include <lwp_arch.h> + +#include <stack.h> +#include <cpuport.h> +#include <encoding.h> + +extern rt_ubase_t MMUTable[]; + +int arch_expand_user_stack(void *addr) +{ + int ret = 0; + rt_ubase_t stack_addr = (rt_ubase_t)addr; + + stack_addr &= ~PAGE_OFFSET_MASK; + if ((stack_addr >= (rt_ubase_t)USER_STACK_VSTART) && (stack_addr < (rt_ubase_t)USER_STACK_VEND)) + { + void *map = lwp_map_user(lwp_self(), (void *)stack_addr, PAGE_SIZE, RT_FALSE); + + if (map || lwp_user_accessable(addr, 1)) + { + ret = 1; + } + } + return ret; +} + +void *lwp_copy_return_code_to_user_stack() +{ + void lwp_thread_return(); + void lwp_thread_return_end(); + rt_thread_t tid = rt_thread_self(); + + if (tid->user_stack != RT_NULL) + { + 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); + return (void *)userstack; + } + + return RT_NULL; +} + +rt_mmu_info *arch_kernel_get_mmu_info(void) +{ + extern rt_mmu_info *mmu_info; + + return mmu_info; +} + +rt_ubase_t lwp_fix_sp(rt_ubase_t cursp) +{ + void lwp_thread_return(); + void lwp_thread_return_end(); + + if (cursp == 0) + { + return 0; + } + + return cursp - ((rt_size_t)lwp_thread_return_end - (rt_size_t)lwp_thread_return); +} + +rt_thread_t rt_thread_sp_to_thread(void *spmember_addr) +{ + return (rt_thread_t)(((rt_ubase_t)spmember_addr) - (offsetof(struct rt_thread, sp))); +} + +void *get_thread_kernel_stack_top(rt_thread_t thread) +{ + return (void *)(((rt_size_t)thread->stack_addr) + ((rt_size_t)thread->stack_size)); +} + +void *arch_get_user_sp(void) +{ + /* user sp saved in interrupt context */ + rt_thread_t self = rt_thread_self(); + rt_uint8_t *stack_top = (rt_uint8_t *)self->stack_addr + self->stack_size; + struct rt_hw_stack_frame *frame = (struct rt_hw_stack_frame *)(stack_top - sizeof(struct rt_hw_stack_frame)); + + return (void *)frame->user_sp_exc_stack; +} + +int arch_user_space_init(struct rt_lwp *lwp) +{ + rt_ubase_t *mmu_table; + + mmu_table = (rt_ubase_t *)rt_pages_alloc(0); + if (!mmu_table) + { + return -1; + } + + lwp->end_heap = USER_HEAP_VADDR; + + rt_memcpy(mmu_table, MMUTable, PAGE_SIZE); + rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, mmu_table, 4 * PAGE_SIZE); + rt_hw_mmu_map_init(&lwp->mmu_info, (void *)USER_VADDR_START, USER_VADDR_TOP - USER_VADDR_START, (rt_size_t *)mmu_table, 0); + + return 0; +} + +void *arch_kernel_mmu_table_get(void) +{ + return (void *)((char *)MMUTable); +} + +void arch_user_space_vtable_free(struct rt_lwp *lwp) +{ + if (lwp && lwp->mmu_info.vtable) + { + rt_pages_free(lwp->mmu_info.vtable, 0); + } +} + +long _sys_clone(void *arg[]); +long sys_clone(void *arg[]) +{ + return _sys_clone(arg); +} + +long _sys_fork(void); +long sys_fork(void) +{ + return _sys_fork(); +} + +long _sys_vfork(void); +long sys_vfork(void) +{ + return _sys_fork(); +} + +/** + * set exec context for fork/clone. + */ +int arch_set_thread_context(void (*exit)(void), void *new_thread_stack, + void *user_stack, void **thread_sp) +{ + RT_ASSERT(exit != RT_NULL); + RT_ASSERT(user_stack != RT_NULL); + RT_ASSERT(new_thread_stack != RT_NULL); + RT_ASSERT(thread_sp != RT_NULL); + struct rt_hw_stack_frame *syscall_frame; + struct rt_hw_stack_frame *thread_frame; + + rt_uint8_t *stk; + rt_uint8_t *syscall_stk; + + stk = (rt_uint8_t *)new_thread_stack; + /* reserve syscall context, all the registers are copyed from parent */ + stk -= CTX_REG_NR * REGBYTES; + syscall_stk = stk; + + syscall_frame = (struct rt_hw_stack_frame *)stk; + + /* modify user sp */ + syscall_frame->user_sp_exc_stack = (rt_ubase_t)user_stack; + + /* skip ecall */ + syscall_frame->epc += 4; + + /* child return value is 0 */ + syscall_frame->a0 = 0; + syscall_frame->a1 = 0; + + /* reset thread area */ + rt_thread_t thread = rt_container_of((unsigned long)thread_sp, struct rt_thread, sp); + syscall_frame->tp = (rt_ubase_t)thread->thread_idr; + +#ifdef ARCH_USING_NEW_CTX_SWITCH + extern void *_rt_hw_stack_init(rt_ubase_t *sp, rt_ubase_t ra, rt_ubase_t sstatus); + rt_ubase_t sstatus = read_csr(sstatus) | SSTATUS_SPP; + sstatus &= ~SSTATUS_SIE; + + /* compatible to RESTORE_CONTEXT */ + stk = (void *)_rt_hw_stack_init((rt_ubase_t *)stk, (rt_ubase_t)exit, sstatus); +#else + /* build temp thread context */ + stk -= sizeof(struct rt_hw_stack_frame); + + thread_frame = (struct rt_hw_stack_frame *)stk; + + int i; + for (i = 0; i < sizeof(struct rt_hw_stack_frame) / sizeof(rt_ubase_t); i++) + { + ((rt_ubase_t *)thread_frame)[i] = 0xdeadbeaf; + } + + /* set pc for thread */ + thread_frame->epc = (rt_ubase_t)exit; + + /* set old exception mode as supervisor, because in kernel */ + thread_frame->sstatus = read_csr(sstatus) | SSTATUS_SPP; + thread_frame->sstatus &= ~SSTATUS_SIE; /* must disable interrupt */ + + /* set stack as syscall stack */ + thread_frame->user_sp_exc_stack = (rt_ubase_t)syscall_stk; + +#endif /* ARCH_USING_NEW_CTX_SWITCH */ + /* save new stack top */ + *thread_sp = (void *)stk; + + /** + * The stack for child thread: + * + * +------------------------+ --> kernel stack top + * | syscall stack | + * | | + * | @sp | --> `user_stack` + * | @epc | --> user ecall addr + 4 (skip ecall) + * | @a0&a1 | --> 0 (for child return 0) + * | | + * +------------------------+ --> temp thread stack top + * | temp thread stack | ^ + * | | | + * | @sp | ---------/ + * | @epc | --> `exit` (arch_clone_exit/arch_fork_exit) + * | | + * +------------------------+ --> thread sp + */ +} + +/** + * void lwp_exec_user(void *args, void *kernel_stack, void *user_entry) + */ +void lwp_exec_user(void *args, void *kernel_stack, void *user_entry) +{ + arch_start_umode(args, user_entry, (void*)USER_STACK_VEND, kernel_stack); +} + +void *arch_get_usp_from_uctx(struct rt_user_context *uctx) +{ + return uctx->sp; +} + +#endif /* RT_USING_USERSPACE */ diff --git a/components/lwp/arch/risc-v/rv64/lwp_arch.h b/components/lwp/arch/risc-v/rv64/lwp_arch.h new file mode 100644 index 0000000000..9e12aa5ba7 --- /dev/null +++ b/components/lwp/arch/risc-v/rv64/lwp_arch.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + */ + +#ifndef LWP_ARCH_H__ +#define LWP_ARCH_H__ + +#include <lwp.h> +#include <lwp_arch_comm.h> +#include <riscv_mmu.h> + +#ifdef RT_USING_USERSPACE + +#ifdef RT_USING_USERSPACE_32BIT_LIMIT +#define USER_HEAP_VADDR 0xF0000000UL +#define USER_HEAP_VEND 0xFE000000UL +#define USER_STACK_VSTART 0xE0000000UL +#define USER_STACK_VEND USER_HEAP_VADDR +#define USER_VADDR_START 0xC0000000UL +#define USER_VADDR_TOP 0xFF000000UL +#define USER_LOAD_VADDR 0xD0000000UL +#define LDSO_LOAD_VADDR USER_LOAD_VADDR +#else +#define USER_HEAP_VADDR 0x300000000UL +#define USER_HEAP_VEND 0xffffffffffff0000UL +#define USER_STACK_VSTART 0x270000000UL +#define USER_STACK_VEND USER_HEAP_VADDR +#define USER_VADDR_START 0x100000000UL +#define USER_VADDR_TOP 0xfffffffffffff000UL +#define USER_LOAD_VADDR 0x200000000 +#define LDSO_LOAD_VADDR 0x200000000 +#endif + +/* this attribution is cpu specified, and it should be defined in riscv_mmu.h */ +#ifndef MMU_MAP_U_RWCB +#define MMU_MAP_U_RWCB 0 +#endif + +#ifndef MMU_MAP_U_RW +#define MMU_MAP_U_RW 0 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +rt_mmu_info* arch_kernel_get_mmu_info(void); + +rt_inline unsigned long rt_hw_ffz(unsigned long x) +{ + return __builtin_ffsl(~x) - 1; +} + +rt_inline void icache_invalid_all(void) +{ + //TODO: +} + +#ifdef __cplusplus +} +#endif + +#endif + +#endif /*LWP_ARCH_H__*/ diff --git a/components/lwp/arch/risc-v/rv64/lwp_gcc.S b/components/lwp/arch/risc-v/rv64/lwp_gcc.S new file mode 100644 index 0000000000..edf8166e77 --- /dev/null +++ b/components/lwp/arch/risc-v/rv64/lwp_gcc.S @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-12-10 Jesven first version + * 2021-02-03 lizhirui port to riscv64 + * 2021-02-19 lizhirui port to new version of rt-smart + * 2022-11-08 Wangxiaoyao Cleanup codes; + * Support new context switch + */ + +#include "rtconfig.h" + +#ifndef __ASSEMBLY__ +#define __ASSEMBLY__ +#endif /* __ASSEMBLY__ */ + +#include "cpuport.h" +#include "encoding.h" +#include "stackframe.h" + +.section .text.lwp + +/* + * void arch_start_umode(args, text, ustack, kstack); + */ +.global arch_start_umode +.type arch_start_umode, % function +arch_start_umode: + // load kstack for user process + csrw sscratch, a3 + li t0, SSTATUS_SPP | SSTATUS_SIE // set as user mode, close interrupt + csrc sstatus, t0 + li t0, SSTATUS_SPIE // enable interrupt when return to user mode + csrs sstatus, t0 + + csrw sepc, a1 + mv a3, a2 + sret//enter user mode + +/* + * void arch_crt_start_umode(args, text, ustack, kstack); + */ +.global arch_crt_start_umode +.type arch_crt_start_umode, % function +arch_crt_start_umode: + li t0, SSTATUS_SPP | SSTATUS_SIE // set as user mode, close interrupt + csrc sstatus, t0 + li t0, SSTATUS_SPIE // enable interrupt when return to user mode + csrs sstatus, t0 + + csrw sepc, a1 + mv s0, a0 + mv s1, a1 + mv s2, a2 + mv s3, a3 + mv a0, s2 + call lwp_copy_return_code_to_user_stack + mv a0, s2 + call lwp_fix_sp + mv sp, a0//user_sp + mv ra, a0//return address + mv a0, s0//args + + csrw sscratch, s3 + sret//enter user mode + +/** + * Unify exit point from kernel mode to enter user space + * we handle following things here: + * 1. restoring user mode debug state (not support yet) + * 2. handling thread's exit request + * 3. handling POSIX signal + * 4. restoring user context + * 5. jump to user mode + */ +.global arch_ret_to_user +arch_ret_to_user: + // TODO: we don't support kernel gdb server in risc-v yet + // so we don't check debug state here and handle debugging bussiness + + call lwp_check_exit_request + beqz a0, 1f + mv a0, x0 + call sys_exit + +1: + call lwp_signal_check + beqz a0, ret_to_user_exit + J user_do_signal + +ret_to_user_exit: + RESTORE_ALL + // `RESTORE_ALL` also reset sp to user sp, and setup sscratch + sret + +/** + * Restore user context from exception frame stroraged in ustack + * And handle pending signals; + */ +arch_signal_quit: + call lwp_signal_restore + call arch_get_usp_from_uctx + // return value is user sp + mv sp, a0 + + // restore user sp before enter trap + addi a0, sp, CTX_REG_NR * REGBYTES + csrw sscratch, a0 + + RESTORE_ALL + SAVE_ALL + j arch_ret_to_user + +/** + * Prepare and enter user signal handler + * Move user exception frame and setup signal return + * routine in user stack + */ +user_do_signal: + /** restore and backup kernel sp carefully to avoid leaking */ + addi t0, sp, CTX_REG_NR * REGBYTES + csrw sscratch, t0 + + RESTORE_ALL + SAVE_ALL + + /** + * save lwp_sigreturn in user memory + */ + mv s0, sp + la t0, lwp_sigreturn + la t1, lwp_sigreturn_end + // t1 <- size + sub t1, t1, t0 + // s0 <- dst + sub s0, s0, t1 + mv s2, t1 +lwp_sigreturn_copy_loop: + addi t2, t1, -1 + add t3, t0, t2 + add t4, s0, t2 + lb t5, 0(t3) + sb t5, 0(t4) + mv t1, t2 + bnez t1, lwp_sigreturn_copy_loop + + /** + * 1. clear sscratch & restore kernel sp to + * enter kernel mode routine + * 2. storage exp frame address to restore context, + * by calling to lwp_signal_backup + * 3. storage lwp_sigreturn entry address + * 4. get signal id as param for signal handler + */ + mv s1, sp + csrrw sp, sscratch, x0 + + /** + * synchronize dcache & icache if target is + * a Harvard Architecture machine, otherwise + * do nothing + */ + mv a0, s0 + mv a1, s2 + call rt_hw_sync_cache_local + + /** + * backup user sp (point to saved exception frame, skip sigreturn routine) + * And get signal id + + * a0: user sp + * a1: user_pc (not used, marked as 0 to avoid abuse) + * a2: user_flag (not used, marked as 0 to avoid abuse) + */ + mv a0, s1 + mv a1, zero + mv a2, zero + call lwp_signal_backup + + /** + * backup signal id in s2, + * and get sighandler by signal id + */ + mv s2, a0 + call lwp_sighandler_get + + /** + * set regiter RA to user signal handler + * set sp to user sp & save kernel sp in sscratch + */ + mv ra, s0 + csrw sscratch, sp + mv sp, s0 + + /** + * a0 is signal_handler, + * s1 = s0 == NULL ? lwp_sigreturn : s0; + */ + mv s1, s0 + beqz a0, skip_user_signal_handler + mv s1, a0 + +skip_user_signal_handler: + // enter user mode and enable interrupt when return to user mode + li t0, SSTATUS_SPP + csrc sstatus, t0 + li t0, SSTATUS_SPIE + csrs sstatus, t0 + + // sepc <- signal_handler + csrw sepc, s1 + // a0 <- signal id + mv a0, s2 + sret + +.align 3 +lwp_debugreturn: + li a7, 0xff + ecall + +.align 3 +lwp_sigreturn: + li a7, 0xfe + ecall + +.align 3 +lwp_sigreturn_end: + +.align 3 +.global lwp_thread_return +lwp_thread_return: + li a0, 0 + li a7, 1 + ecall + +.align 3 +.global lwp_thread_return_end +lwp_thread_return_end: + +.globl arch_get_tidr +arch_get_tidr: + mv a0, tp + ret + +.global arch_set_thread_area +arch_set_thread_area: +.globl arch_set_tidr +arch_set_tidr: + mv tp, a0 + ret + +.global arch_clone_exit +.global arch_fork_exit +arch_fork_exit: +arch_clone_exit: + j arch_syscall_exit + +.global syscall_entry +syscall_entry: +#ifndef ARCH_USING_NEW_CTX_SWITCH + //swap to thread kernel stack + csrr t0, sstatus + andi t0, t0, 0x100 + beqz t0, __restore_sp_from_tcb + +__restore_sp_from_sscratch: // from kernel + csrr t0, sscratch + j __move_stack_context + +__restore_sp_from_tcb: // from user + la a0, rt_current_thread + LOAD a0, 0(a0) + jal get_thread_kernel_stack_top + mv t0, a0 + +__move_stack_context: + mv t1, sp//src + mv sp, t0//switch stack + addi sp, sp, -CTX_REG_NR * REGBYTES + //copy context + li s0, CTX_REG_NR//cnt + mv t2, sp//dst + +copy_context_loop: + LOAD t0, 0(t1) + STORE t0, 0(t2) + addi s0, s0, -1 + addi t1, t1, 8 + addi t2, t2, 8 + bnez s0, copy_context_loop +#endif /* ARCH_USING_NEW_CTX_SWITCH */ + + /* fetch SYSCALL ID */ + LOAD a7, 17 * REGBYTES(sp) + addi a7, a7, -0xfe + beqz a7, arch_signal_quit + +#ifdef RT_USING_USERSPACE + /* save setting when syscall enter */ + call rt_thread_self + call lwp_user_setting_save +#endif + + mv a0, sp + OPEN_INTERRUPT + call syscall_handler + j arch_syscall_exit + +.global arch_syscall_exit +arch_syscall_exit: + CLOSE_INTERRUPT + + #if defined(RT_USING_USERSPACE) + LOAD s0, 2 * REGBYTES(sp) + andi s0, s0, 0x100 + bnez s0, dont_ret_to_user + j arch_ret_to_user + #endif +dont_ret_to_user: + +#ifdef RT_USING_USERSPACE + /* restore setting when syscall exit */ + call rt_thread_self + call lwp_user_setting_restore + + /* after restore the reg `tp`, need modify context */ + STORE tp, 4 * REGBYTES(sp) +#endif + + //restore context + RESTORE_ALL + csrw sscratch, zero + sret diff --git a/components/lwp/arch/risc-v/rv64/reloc.c b/components/lwp/arch/risc-v/rv64/reloc.c new file mode 100644 index 0000000000..b35f8bef27 --- /dev/null +++ b/components/lwp/arch/risc-v/rv64/reloc.c @@ -0,0 +1,108 @@ +#include <rtthread.h> +#include <stdint.h> +#include <string.h> +#include <elf.h> +#ifdef RT_USING_USERSPACE +#include <mmu.h> +#include <page.h> +#endif + +typedef struct +{ + Elf64_Word st_name; + Elf64_Addr st_value; + Elf64_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf64_Half st_shndx; +} Elf64_sym; + +#ifdef RT_USING_USERSPACE +void arch_elf_reloc(rt_mmu_info *m_info, void *text_start, void *rel_dyn_start, size_t rel_dyn_size, void *got_start, size_t got_size, Elf64_sym *dynsym) +{ + size_t rel_off; + void* addr; + + if (rel_dyn_size && !dynsym) + { + return; + } + for (rel_off = 0; rel_off < rel_dyn_size; rel_off += 8) + { + uint32_t v1, v2; + + addr = rt_hw_mmu_v2p(m_info, (void *)(((rt_size_t)rel_dyn_start) + rel_off)); + memcpy(&v1, addr, 4); + addr = rt_hw_mmu_v2p(m_info, (void *)(((rt_size_t)rel_dyn_start) + rel_off + 4)); + memcpy(&v2, addr, 4); + + addr = rt_hw_mmu_v2p(m_info, (void *)((rt_size_t)text_start + v1)); + if ((v2 & 0xff) == R_ARM_RELATIVE) + { + *(rt_size_t*)addr += (rt_size_t)text_start; + } + else if ((v2 & 0xff) == R_ARM_ABS32) + { + uint32_t t; + t = (v2 >> 8); + if (t) /* 0 is UDF */ + { + *(rt_size_t*)addr = (((rt_size_t)text_start) + dynsym[t].st_value); + } + } + } + /* modify got */ + if (got_size) + { + uint32_t *got_item = (uint32_t*)got_start; + + for (rel_off = 0; rel_off < got_size; rel_off += 4, got_item++) + { + addr = rt_hw_mmu_v2p(m_info, got_item); + *(rt_size_t *)addr += (rt_size_t)text_start; + } + } +} +#else + +void arch_elf_reloc(void *text_start, void *rel_dyn_start, size_t rel_dyn_size, void *got_start, size_t got_size, Elf64_sym *dynsym) +{ + size_t rel_off; + + if (rel_dyn_size && !dynsym) + { + return; + } + for (rel_off = 0; rel_off < rel_dyn_size; rel_off += 8) + { + uint32_t v1, v2; + + memcpy(&v1, ((rt_uint8_t *)rel_dyn_start) + rel_off, 4); + memcpy(&v2, ((rt_uint8_t *)rel_dyn_start) + rel_off + 4, 4); + + if ((v2 & 0xff) == R_ARM_RELATIVE) + { + *(uint32_t*)(((rt_size_t)text_start) + v1) += (uint32_t)text_start; + } + else if ((v2 & 0xff) == R_ARM_ABS32) + { + uint32_t t; + t = (v2 >> 8); + if (t) /* 0 is UDF */ + { + *(uint32_t*)(((rt_size_t)text_start) + v1) = (uint32_t)(((rt_size_t)text_start) + dynsym[t].st_value); + } + } + } + /* modify got */ + if (got_size) + { + uint32_t *got_item = (uint32_t*)got_start; + + for (rel_off = 0; rel_off < got_size; rel_off += 4, got_item++) + { + *got_item += (uint32_t)text_start; + } + } +} +#endif diff --git a/components/lwp/arch/x86/i386/SConscript b/components/lwp/arch/x86/i386/SConscript new file mode 100644 index 0000000000..c0d3aead77 --- /dev/null +++ b/components/lwp/arch/x86/i386/SConscript @@ -0,0 +1,11 @@ +# RT-Thread building script for component + +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') + Glob('*.S') +CPPPATH = [cwd] + +group = DefineGroup('lwp-x86-i386', src, depend = ['RT_USING_LWP'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/lwp/arch/x86/i386/lwp_arch.c b/components/lwp/arch/x86/i386/lwp_arch.c new file mode 100644 index 0000000000..5ad150121b --- /dev/null +++ b/components/lwp/arch/x86/i386/lwp_arch.c @@ -0,0 +1,371 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-7-14 JasonHu first version + */ + +#include <rthw.h> +#include <stddef.h> +#include <rtconfig.h> +#include <rtdbg.h> + +#ifdef RT_USING_USERSPACE + +#include <stackframe.h> +#include <interrupt.h> +#include <segment.h> + +#include <mmu.h> +#include <page.h> +#include <lwp_mm_area.h> +#include <lwp_user_mm.h> +#include <lwp_arch.h> + +#ifdef RT_USING_SIGNALS +#include <lwp_signal.h> +#endif /* RT_USING_SIGNALS */ + +extern size_t g_mmu_table[]; + +int arch_expand_user_stack(void *addr) +{ + int ret = 0; + size_t stack_addr = (size_t)addr; + + stack_addr &= ~PAGE_OFFSET_MASK; + if ((stack_addr >= (size_t)USER_STACK_VSTART) && (stack_addr < (size_t)USER_STACK_VEND)) + { + void *map = lwp_map_user(lwp_self(), (void *)stack_addr, PAGE_SIZE, RT_FALSE); + + if (map || lwp_user_accessable(addr, 1)) + { + ret = 1; /* map success */ + } + else /* map failed, send signal SIGSEGV */ + { +#ifdef RT_USING_SIGNALS + dbg_log(DBG_ERROR, "[fault] thread %s mapped addr %p failed!\n", rt_thread_self()->name, addr); + lwp_thread_kill(rt_thread_self(), SIGSEGV); + ret = 1; /* return 1, will return back to intr, then check exit */ +#endif + } + } + else /* not stack, send signal SIGSEGV */ + { +#ifdef RT_USING_SIGNALS + dbg_log(DBG_ERROR, "[fault] thread %s access unmapped addr %p!\n", rt_thread_self()->name, addr); + lwp_thread_kill(rt_thread_self(), SIGSEGV); + ret = 1; /* return 1, will return back to intr, then check exit */ +#endif + } + return ret; +} + +void *get_thread_kernel_stack_top(rt_thread_t thread) +{ + return RT_NULL; +} + +/** + * don't support this in i386, it's ok! + */ +void *arch_get_user_sp() +{ + return RT_NULL; +} + +int arch_user_space_init(struct rt_lwp *lwp) +{ + rt_size_t *mmu_table; + + mmu_table = (rt_size_t *)rt_pages_alloc(0); + if (!mmu_table) + { + return -1; + } + rt_memset(mmu_table, 0, ARCH_PAGE_SIZE); + + lwp->end_heap = USER_HEAP_VADDR; + memcpy(mmu_table, g_mmu_table, ARCH_PAGE_SIZE / 4); + memset((rt_uint8_t *)mmu_table + ARCH_PAGE_SIZE / 4, 0, ARCH_PAGE_SIZE / 4 * 3); + rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, mmu_table, ARCH_PAGE_SIZE); + if (rt_hw_mmu_map_init(&lwp->mmu_info, (void*)USER_VADDR_START, USER_VADDR_TOP - USER_VADDR_START, mmu_table, PV_OFFSET) < 0) + { + rt_pages_free(mmu_table, 0); + return -1; + } + return 0; +} + +void *arch_kernel_mmu_table_get(void) +{ + return (void *)((char *)g_mmu_table); +} + +void arch_user_space_vtable_free(struct rt_lwp *lwp) +{ + if (lwp && lwp->mmu_info.vtable) + { + rt_pages_free(lwp->mmu_info.vtable, 0); + lwp->mmu_info.vtable = NULL; + } +} + +void arch_set_thread_area(void *p) +{ + rt_hw_seg_tls_set((rt_ubase_t) p); + rt_thread_t cur = rt_thread_self(); + cur->thread_idr = p; /* update thread idr after first set */ +} + +void *arch_get_tidr(void) +{ + rt_thread_t cur = rt_thread_self(); + if (!cur->lwp) /* no lwp, don't get thread idr from tls seg */ + return NULL; + return (void *)rt_hw_seg_tls_get(); /* get thread idr from tls seg */ +} + +void arch_set_tidr(void *p) +{ + rt_thread_t cur = rt_thread_self(); + if (!cur->lwp) /* no lwp, don't set thread idr to tls seg */ + return; + rt_hw_seg_tls_set((rt_ubase_t) p); /* set tls seg addr as thread idr */ +} + +static void lwp_user_stack_init(rt_hw_stack_frame_t *frame) +{ + frame->ds = frame->es = USER_DATA_SEL; + frame->cs = USER_CODE_SEL; + frame->ss = USER_STACK_SEL; + frame->gs = USER_TLS_SEL; + frame->fs = 0; /* unused */ + + frame->edi = frame->esi = \ + frame->ebp = frame->esp_dummy = 0; + frame->eax = frame->ebx = \ + frame->ecx = frame->edx = 0; + + frame->error_code = 0; + frame->vec_no = 0; + + frame->eflags = (EFLAGS_MBS | EFLAGS_IF_1 | EFLAGS_IOPL_3); +} + +extern void lwp_switch_to_user(void *frame); +/** + * user entry, set frame. + * at the end of execute, we need enter user mode, + * in x86, we can set stack, arg, text entry in a stack frame, + * then pop then into register, final use iret to switch kernel mode to user mode. + */ +void arch_start_umode(void *args, const void *text, void *ustack, void *k_stack) +{ + rt_uint8_t *stk = k_stack; + stk -= sizeof(struct rt_hw_stack_frame); + struct rt_hw_stack_frame *frame = (struct rt_hw_stack_frame *)stk; + + lwp_user_stack_init(frame); + frame->esp = (rt_uint32_t)ustack - 32; + frame->ebx = (rt_uint32_t)args; + frame->eip = (rt_uint32_t)text; + lwp_switch_to_user(frame); + /* should never return */ +} + +void lwp_exec_user(void *args, void *kernel_stack, void *user_entry) +{ + arch_start_umode(args, (const void *)user_entry, (void *)USER_STACK_VEND, kernel_stack); +} + +extern void lwp_thread_return(); +extern void lwp_thread_return_end(); + +static void *lwp_copy_return_code_to_user_stack(void *ustack) +{ + size_t size = (size_t)lwp_thread_return_end - (size_t)lwp_thread_return; + void *retcode = (void *)((size_t)ustack - size); + memcpy(retcode, (void *)lwp_thread_return, size); + return retcode; +} + +/** + * when called sys_thread_create, need create a thread, after thread stared, will come here, + * like arch_start_umode, will enter user mode, but we must set thread exit function. it looks like: + * void func(void *arg) + * { + * ... + * } + * when thread func return, we must call exit code to exit thread, or not the program runs away. + * so we need copy exit code to user and call exit code when func return. + */ +void arch_crt_start_umode(void *args, const void *text, void *ustack, void *k_stack) +{ + RT_ASSERT(ustack != NULL); + + rt_uint8_t *stk; + stk = (rt_uint8_t *)((rt_uint8_t *)k_stack + sizeof(rt_ubase_t)); + stk = (rt_uint8_t *)RT_ALIGN_DOWN(((rt_ubase_t)stk), sizeof(rt_ubase_t)); + stk -= sizeof(struct rt_hw_stack_frame); + struct rt_hw_stack_frame *frame = (struct rt_hw_stack_frame *)stk; + + lwp_user_stack_init(frame); + + /* make user thread stack */ + unsigned long *retcode = lwp_copy_return_code_to_user_stack(ustack); /* copy ret code */ + unsigned long *retstack = (unsigned long *)RT_ALIGN_DOWN(((rt_ubase_t)retcode), sizeof(rt_ubase_t)); + + /** + * x86 call stack + * + * retcode here + * + * arg n + * arg n - 1 + * ... + * arg 2 + * arg 1 + * arg 0 + * eip (caller return addr, point to retcode) + * esp + */ + *(--retstack) = (unsigned long) args; /* arg */ + *(--retstack) = (unsigned long) retcode; /* ret eip */ + + frame->esp = (rt_uint32_t)retstack; + frame->eip = (rt_uint32_t)text; + lwp_switch_to_user(frame); + /* should never return */ +} + +rt_thread_t rt_thread_sp_to_thread(void *spmember_addr) +{ + return (rt_thread_t)(((rt_ubase_t)spmember_addr) - (offsetof(struct rt_thread, sp))); +} + +/** + * set exec context for fork/clone. + * user_stack(unused) + */ +void arch_set_thread_context(void *exit_addr, void *new_thread_stack, void *user_stack, void **thread_sp) +{ + /** + * thread kernel stack was set to tss.esp0, when intrrupt/syscall occur, + * the stack frame will store in kernel stack top, so we can get the stack + * frame by kernel stack top. + */ + rt_hw_stack_frame_t *frame = (rt_hw_stack_frame_t *)((rt_ubase_t)new_thread_stack - sizeof(rt_hw_stack_frame_t)); + + frame->eax = 0; /* child return 0 */ + + rt_hw_context_t *context = (rt_hw_context_t *) (((rt_uint32_t *)frame) - HW_CONTEXT_MEMBER_NR); + context->eip = (void *)exit_addr; /* when thread started, jump to intr exit for enter user mode */ + context->ebp = context->ebx = context->esi = context->edi = 0; + + /** + * set sp as the address of first member of rt_hw_context, + * when scheduler call switch, pop stack from context stack. + */ + *thread_sp = (void *)&context->ebp; + + /** + * after set context, the stack like this: + * + * ----------- + * stack frame| eax = 0 + * ----------- + * context(only HW_CONTEXT_MEMBER_NR)| eip = rt_hw_intr_exit + * ----------- + * thread sp | to <- rt_hw_context_switch(from, to) + * ----------- + */ +} + +#ifdef RT_USING_SIGNALS + +#define SIGNAL_RET_CODE_SIZE 16 + +struct rt_signal_frame +{ + char *ret_addr; /* return addr when handler return */ + int signo; /* signal for user handler arg */ + rt_hw_stack_frame_t frame; /* save kernel signal stack */ + char ret_code[SIGNAL_RET_CODE_SIZE]; /* save return code */ +}; +typedef struct rt_signal_frame rt_signal_frame_t; + +extern void lwp_signal_return(); +extern void lwp_signal_return_end(); + +void lwp_try_do_signal(rt_hw_stack_frame_t *frame) +{ + if (!lwp_signal_check()) + return; + + /* 1. backup signal mask */ + int signal = lwp_signal_backup((void *) frame->esp, (void *) frame->eip, (void *) frame->eflags); + + /* 2. get signal handler */ + lwp_sighandler_t handler = lwp_sighandler_get(signal); + if (handler == RT_NULL) /* no handler, ignore */ + { + lwp_signal_restore(); + return; + } + + rt_base_t level = rt_hw_interrupt_disable(); + /* 3. backup frame */ + rt_signal_frame_t *sig_frame = (rt_signal_frame_t *)((frame->esp - sizeof(rt_signal_frame_t)) & -8UL); + memcpy(&sig_frame->frame, frame, sizeof(rt_hw_stack_frame_t)); + sig_frame->signo = signal; + + /** + * 4. copy user return code into user stack + * + * save current frame on user stack. the user stack like: + * + * ---------- + * user code stack + * ----------+ -> esp before enter kernel + * signal frame + * ----------+ -> esp when handle signal handler + * signal handler stack + * ---------- + */ + size_t ret_code_size = (size_t)lwp_signal_return_end - (size_t)lwp_signal_return; + memcpy(sig_frame->ret_code, (void *)lwp_signal_return, ret_code_size); + sig_frame->ret_addr = sig_frame->ret_code; + + /* 5. jmp to user execute handler, update frame register info */ + lwp_user_stack_init(frame); + frame->eip = (rt_uint32_t) handler; + frame->esp = (rt_uint32_t) sig_frame; + + rt_hw_interrupt_enable(level); +} + +void lwp_signal_do_return(rt_hw_stack_frame_t *frame) +{ + /** + * ASSUME: in x86, each stack push and pop element is 4 byte. so STACK_ELEM_SIZE = sizeof(int) => 4. + * when signal handler return, the stack move to the buttom of signal frame. + * but return will pop eip from esp, then {esp += STACK_ELEM_SIZE}, thus {esp = (signal frame) + STACK_ELEM_SIZE}. + * so {(signal frame) = esp - STACK_ELEM_SIZE} + */ + rt_signal_frame_t *sig_frame = (rt_signal_frame_t *)(frame->esp - sizeof(rt_uint32_t)); + memcpy(frame, &sig_frame->frame, sizeof(rt_hw_stack_frame_t)); + + /** + * restore signal info, but don't use rt_user_context, + * we use sig_frame to restore stack frame + */ + lwp_signal_restore(); +} +#endif /* RT_USING_SIGNALS */ + +#endif /* RT_USING_USERSPACE */ diff --git a/components/lwp/arch/x86/i386/lwp_arch.h b/components/lwp/arch/x86/i386/lwp_arch.h new file mode 100644 index 0000000000..f9a56ca3f5 --- /dev/null +++ b/components/lwp/arch/x86/i386/lwp_arch.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-07-18 JasonHu first version + */ + +#ifndef LWP_ARCH_H__ +#define LWP_ARCH_H__ + +#include <lwp.h> +#include <lwp_arch_comm.h> +#include <stackframe.h> + +#ifdef RT_USING_USERSPACE +#define USER_VADDR_TOP 0xFFFFF000UL +#define USER_HEAP_VEND 0xE0000000UL +#define USER_HEAP_VADDR 0x90000000UL +#define USER_STACK_VSTART 0x80000000UL +#define USER_STACK_VEND USER_HEAP_VADDR +#define LDSO_LOAD_VADDR 0x70000000UL +#define USER_VADDR_START 0x40000000UL +#define USER_LOAD_VADDR USER_VADDR_START + +#define SIGNAL_RETURN_SYSCAL_ID 0xe000 + +#ifdef __cplusplus +extern "C" { +#endif + +rt_thread_t rt_thread_sp_to_thread(void *spmember_addr); + +void lwp_signal_do_return(rt_hw_stack_frame_t *frame); + +rt_inline unsigned long rt_hw_ffz(unsigned long x) +{ + return __builtin_ffsl(~x) - 1; +} + +#ifdef __cplusplus +} +#endif + +#endif /* RT_USING_USERSPACE */ + +#endif /*LWP_ARCH_H__*/ diff --git a/components/lwp/arch/x86/i386/lwp_gcc.S b/components/lwp/arch/x86/i386/lwp_gcc.S new file mode 100644 index 0000000000..c1245ebe11 --- /dev/null +++ b/components/lwp/arch/x86/i386/lwp_gcc.S @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-7-14 JasonHu first version + */ + +#include "rtconfig.h" + +.section .text.lwp + +/* + * void lwp_switch_to_user(frame); + */ +.global lwp_switch_to_user +lwp_switch_to_user: + movl 0x4(%esp), %esp + addl $4,%esp // skip intr no + popal + popl %gs + popl %fs + popl %es + popl %ds + addl $4, %esp // skip error_code + iret // enter to user mode + +.extern arch_syscall_exit +.global sys_fork +.global sys_vfork +.global arch_fork_exit +sys_fork: +sys_vfork: + jmp _sys_fork +arch_fork_exit: + jmp arch_syscall_exit + +.global sys_clone +.global arch_clone_exit +sys_clone: + jmp _sys_clone +arch_clone_exit: + jmp arch_syscall_exit + +/** + * rt thread return code + */ +.align 4 +.global lwp_thread_return +lwp_thread_return: + movl $1, %eax // eax = 1, sys_exit + movl $0, %ebx + int $0x80 +.align 4 +.global lwp_thread_return_end +lwp_thread_return_end: + +#ifdef RT_USING_SIGNALS +/** + * signal return code + */ +.align 4 +.global lwp_signal_return +lwp_signal_return: + movl $0xe000, %eax // special syscall id for return code + int $0x80 +.align 4 +.global lwp_signal_return_end +lwp_signal_return_end: + +#endif /* RT_USING_SIGNALS */ diff --git a/components/lwp/arch/x86/i386/reloc.c b/components/lwp/arch/x86/i386/reloc.c new file mode 100644 index 0000000000..9677bd65c6 --- /dev/null +++ b/components/lwp/arch/x86/i386/reloc.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-07-28 JasonHu first version + */ + +#include <rtthread.h> +#include <stdint.h> +#include <string.h> +#include <elf.h> +#ifdef RT_USING_USERSPACE +#include <mmu.h> +#include <page.h> +#endif + +typedef struct +{ + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; +} Elf32_sym; + +#ifdef RT_USING_USERSPACE +void arch_elf_reloc(rt_mmu_info *m_info, void *text_start, void *rel_dyn_start, size_t rel_dyn_size, void *got_start, size_t got_size, Elf32_sym *dynsym) +{ + +} +#else + +void arch_elf_reloc(void *text_start, void *rel_dyn_start, size_t rel_dyn_size, void *got_start, size_t got_size, Elf32_sym *dynsym) +{ + +} +#endif |
