summaryrefslogtreecommitdiff
path: root/components/lwp/arch
diff options
context:
space:
mode:
authorguo <[email protected]>2022-12-03 12:07:44 +0800
committerGitHub <[email protected]>2022-12-03 12:07:44 +0800
commitecf2d8215961ca7c539132b62a72df6072cc3e14 (patch)
tree59005f0f74f2593c0435059264f624c862a89f55 /components/lwp/arch
parentaaf5462c6d4ae9466a0a8cd2a4bb00cfe1fef2f2 (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')
-rw-r--r--components/lwp/arch/aarch64/common/reloc.c28
-rw-r--r--components/lwp/arch/aarch64/cortex-a/lwp_arch.c77
-rw-r--r--components/lwp/arch/aarch64/cortex-a/lwp_arch.h45
-rw-r--r--components/lwp/arch/aarch64/cortex-a/lwp_gcc.S593
-rw-r--r--components/lwp/arch/arm/arm926/lwp_gcc.S81
-rw-r--r--components/lwp/arch/arm/common/reloc.c120
-rw-r--r--components/lwp/arch/arm/cortex-a/lwp_arch.c138
-rw-r--r--components/lwp/arch/arm/cortex-a/lwp_arch.h49
-rw-r--r--components/lwp/arch/arm/cortex-a/lwp_gcc.S379
-rw-r--r--components/lwp/arch/arm/cortex-a9/lwp_gcc.S70
-rw-r--r--components/lwp/arch/arm/cortex-m3/lwp_gcc.S124
-rw-r--r--components/lwp/arch/arm/cortex-m3/lwp_iar.S123
-rw-r--r--components/lwp/arch/arm/cortex-m3/lwp_rvds.S135
-rw-r--r--components/lwp/arch/arm/cortex-m4/lwp_gcc.S124
-rw-r--r--components/lwp/arch/arm/cortex-m4/lwp_iar.S123
-rw-r--r--components/lwp/arch/arm/cortex-m4/lwp_rvds.S135
-rw-r--r--components/lwp/arch/arm/cortex-m7/lwp_gcc.S124
-rw-r--r--components/lwp/arch/arm/cortex-m7/lwp_iar.S123
-rw-r--r--components/lwp/arch/arm/cortex-m7/lwp_rvds.S135
-rw-r--r--components/lwp/arch/risc-v/rv64/SConscript11
-rw-r--r--components/lwp/arch/risc-v/rv64/lwp_arch.c264
-rw-r--r--components/lwp/arch/risc-v/rv64/lwp_arch.h70
-rw-r--r--components/lwp/arch/risc-v/rv64/lwp_gcc.S337
-rw-r--r--components/lwp/arch/risc-v/rv64/reloc.c108
-rw-r--r--components/lwp/arch/x86/i386/SConscript11
-rw-r--r--components/lwp/arch/x86/i386/lwp_arch.c371
-rw-r--r--components/lwp/arch/x86/i386/lwp_arch.h49
-rw-r--r--components/lwp/arch/x86/i386/lwp_gcc.S73
-rw-r--r--components/lwp/arch/x86/i386/reloc.c41
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