Преглед изворни кода

[riscv] process switch using less context

wangxiaoyao пре 3 година
родитељ
комит
906c193e86

+ 16 - 3
bsp/qemu-virt64-riscv/Kconfig

@@ -17,10 +17,12 @@ config PKGS_DIR
 
 source "$RTT_DIR/Kconfig"
 source "$PKGS_DIR/Kconfig"
+source "driver/Kconfig"
 
-config BOARD_virt
+config BOARD_QEMU_VIRT_RV64
     bool
     select ARCH_RISCV64
+    select ARCH_CONTEXT_EXTEND
     select RT_USING_COMPONENTS_INIT
     select RT_USING_USER_MAIN
     select RT_USING_CACHE
@@ -39,6 +41,19 @@ config ENABLE_VECTOR
     bool "Using RISC-V Vector Extension"
     default n
 
+if ENABLE_VECTOR
+    choice
+    prompt "Vector Registers Length in Bits"
+    default ARCH_VECTOR_VLEN_128
+    
+    config ARCH_VECTOR_VLEN_128
+        bool "128"
+
+    config ARCH_VECTOR_VLEN_256
+        bool "256"
+    endchoice
+endif
+
 config RT_USING_USERSPACE_32BIT_LIMIT
     bool "Enable userspace 32bit limit"
     default n
@@ -47,8 +62,6 @@ config RT_USING_VIRTIO_MMIO_ALIGN
     bool "Open packed attribution, this may caused an error on virtio"
     default n
 
-source "driver/Kconfig"
-
 config __STACKSIZE__
     int "stack size for interrupt"
     default 4096

+ 0 - 1
components/lwp/arch/risc-v/rv64/lwp_gcc.S

@@ -12,7 +12,6 @@
 
 #include "rtconfig.h"
 
-#define __ASSEMBLY__
 #include "cpuport.h"
 #include "encoding.h"
 #include "stackframe.h"

+ 0 - 20
libcpu/risc-v/virt64/context.h

@@ -1,20 +0,0 @@
-/*
- * Copyright (c) 2006-2022, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date           Author       Notes
- * 2022-10-10     RT-Thread    the first version
- */
-
-#ifndef __CONTEXT_H__
-#define __CONTEXT_H__
-
-void rt_hw_vector_ctx_save(void *buf);
-void rt_hw_vector_ctx_restore(void *buf);
-
-void rt_hw_disable_vector();
-void rt_hw_enable_vector();
-
-#endif /* __CONTEXT_H__ */

+ 73 - 28
libcpu/risc-v/virt64/context_gcc.S

@@ -10,11 +10,74 @@
  * 2021/02/02     lizhirui     Add userspace support
  */
 
-#define __ASSEMBLY__
 #include "cpuport.h"
 #include "stackframe.h"
 
-    .globl rt_hw_context_switch_to
+/**
+ * sstatus -> interrupt frame
+ * sepc -> interrupt frame
+ * sscratch -> ?
+ * sp -> TCB
+ * tp -> pointer to current TCB
+ */
+
+.macro PUSH_8 reg
+    addi    sp, sp, -8
+    STORE   \reg, (sp)
+.endm
+
+.macro POP_8 reg
+    LOAD    \reg, (sp)
+    addi    sp, sp, 8
+.endm
+
+.macro RESERVE_CONTEXT
+    PUSH_8  tp
+    PUSH_8  ra
+    PUSH_8  s0
+    PUSH_8  s1
+    PUSH_8  s2
+    PUSH_8  s3
+    PUSH_8  s4
+    PUSH_8  s5
+    PUSH_8  s6
+    PUSH_8  s7
+    PUSH_8  s8
+    PUSH_8  s9
+    PUSH_8  s10
+    PUSH_8  s11
+    csrr    s11, sstatus
+    li      s10, (SSTATUS_SPP)
+    or      s11, s11, s10
+    PUSH_8  s11
+.endm
+
+.macro RESTORE_CONTEXT
+    POP_8   s11
+    csrw    sstatus, s11
+    POP_8   s11
+    POP_8   s10
+    POP_8   s9
+    POP_8   s8
+    POP_8   s7
+    POP_8   s6
+    POP_8   s5
+    POP_8   s4
+    POP_8   s3
+    POP_8   s2
+    POP_8   s1
+    POP_8   s0
+    POP_8   ra
+    POP_8   tp
+    csrw    sepc, ra
+.endm
+
+/*
+ * void rt_hw_context_switch_to(rt_ubase_t to);
+ *
+ * a0 --> to SP pointer
+ */
+.globl rt_hw_context_switch_to
 rt_hw_context_switch_to:
     LOAD sp, (a0)
 
@@ -26,7 +89,7 @@ rt_hw_context_switch_to:
         jal lwp_mmu_switch
     #endif
 
-    RESTORE_ALL
+    RESTORE_CONTEXT
     sret
 
 /*
@@ -34,32 +97,18 @@ rt_hw_context_switch_to:
  *
  * a0 --> from SP pointer
  * a1 --> to SP pointer
+ *
+ * It should only be used on local interrupt disable
  */
-    .globl rt_hw_context_switch
+.globl rt_hw_context_switch
 rt_hw_context_switch:
-    // backup prev stack top of from thread
-    csrw sscratch, sp
-
-    // on sret, reset status to
-    // 1. interrupt DISABLE
-    // 2. cpu in supervisor mode
-    // 3. reserved other status
-    li t0, 0x120
-    csrs sstatus, t0
-
-    // simulate a exception return to supervisor mode
-    // by storing ra in sepc of from-thread stack frame
-    csrw sepc, ra
-
-    // NOTE: we do NOT guarantee that any temporary registers
-    // will remains their value after SAVE_ALL
-    SAVE_ALL
-
+    RESERVE_CONTEXT
     STORE sp, (a0)
 
-    // restore to thread context
+    // restore to thread SP
     LOAD sp, (a1)
 
+    // restore Address Space
     la s0, rt_current_thread
     LOAD s1, (s0)
 
@@ -68,11 +117,7 @@ rt_hw_context_switch:
         jal lwp_mmu_switch
     #endif
 
-    LOAD t0, 2 * REGBYTES(sp)
-    andi t0, t0, 0x100
-    beqz t0, arch_ret_to_user
-
-    RESTORE_ALL
+    RESTORE_CONTEXT
     sret
 
 #ifdef ENABLE_VECTOR

+ 39 - 40
libcpu/risc-v/virt64/cpuport.c

@@ -17,27 +17,30 @@
 
 #include <lwp_arch.h>
 
+#define K_SSTATUS_DEFAULT (SSTATUS_SPP | SSTATUS_SPIE | SSTATUS_SUM)
 
 /**
  * @brief from thread used interrupt context switch
  *
  */
-volatile rt_ubase_t  rt_interrupt_from_thread = 0;
+volatile rt_ubase_t rt_interrupt_from_thread = 0;
 /**
  * @brief to thread used interrupt context switch
  *
  */
-volatile rt_ubase_t  rt_interrupt_to_thread   = 0;
+volatile rt_ubase_t rt_interrupt_to_thread = 0;
 /**
  * @brief flag to indicate context switch in interrupt or not
  *
  */
 volatile rt_ubase_t rt_thread_switch_interrupt_flag = 0;
 
-
 /**
- * This function will initialize thread stack
+ * This function will initialize thread stack, we assuming
+ * when scheduler restore this new thread, context will restore
+ * an entry to user first application
  *
+ * s0-s11, ra, sstatus, a0
  * @param tentry the entry of thread
  * @param parameter the parameter of entry
  * @param stack_addr the beginning stack address
@@ -45,41 +48,38 @@ volatile rt_ubase_t rt_thread_switch_interrupt_flag = 0;
  *
  * @return stack address
  */
-rt_uint8_t *rt_hw_stack_init(void       *tentry,
-                             void       *parameter,
+rt_uint8_t *rt_hw_stack_init(void *tentry,
+                             void *parameter,
                              rt_uint8_t *stack_addr,
-                             void       *texit)
+                             void *texit)
 {
-    struct rt_hw_stack_frame *frame;
-    rt_uint8_t         *stk;
-    int                i;
-    extern int __global_pointer$;
-
-    stk  = stack_addr + sizeof(rt_ubase_t);
-    stk  = (rt_uint8_t *)RT_ALIGN_DOWN((rt_ubase_t)stk, REGBYTES);
-    stk -= sizeof(struct rt_hw_stack_frame);
-
-    frame = (struct rt_hw_stack_frame *)stk;
-
-    for (i = 0; i < sizeof(struct rt_hw_stack_frame) / sizeof(rt_ubase_t); i++)
-    {
-        ((rt_ubase_t *)frame)[i] = 0xdeadbeef;
-    }
-
-    frame->ra      = (rt_ubase_t)texit;
-    frame->gp      = (rt_ubase_t)&__global_pointer$;
-    frame->a0      = (rt_ubase_t)parameter;
-    frame->epc     = (rt_ubase_t)tentry;
-    frame->user_sp_exc_stack = (rt_ubase_t)(((rt_ubase_t)stk) + sizeof(struct rt_hw_stack_frame));
-
-    /* force to supervisor mode(SPP=1) and set SPIE and SUM to 1 */
-#ifdef ENABLE_FPU
-    frame->sstatus = 0x00046120;    /* enable FPU */
-#else
-    frame->sstatus = 0x00040120;
-#endif
-
-    return stk;
+    rt_ubase_t *sp = (rt_ubase_t *)stack_addr;
+    // we use a strict alignment requirement for Q extension
+    sp = (rt_ubase_t *)RT_ALIGN_DOWN((rt_ubase_t)sp, 16);
+
+    (*--sp) = (rt_ubase_t)tentry;
+    (*--sp) = (rt_ubase_t)parameter;
+    (*--sp) = (rt_ubase_t)texit;
+
+    /* compatible to RESTORE_CONTEXT */
+    extern void _rt_thread_entry(void);
+    (*--sp) = 0;                                /* tp */
+    (*--sp) = (rt_ubase_t)_rt_thread_entry;     /* ra */
+    (*--sp) = 0;                                /* s0(fp) */
+    (*--sp) = 0;                                /* s1 */
+    (*--sp) = 0;                                /* s2 */
+    (*--sp) = 0;                                /* s3 */
+    (*--sp) = 0;                                /* s4 */
+    (*--sp) = 0;                                /* s5 */
+    (*--sp) = 0;                                /* s6 */
+    (*--sp) = 0;                                /* s7 */
+    (*--sp) = 0;                                /* s8 */
+    (*--sp) = 0;                                /* s9 */
+    (*--sp) = 0;                                /* s10 */
+    (*--sp) = 0;                                /* s11 */
+    (*--sp) = K_SSTATUS_DEFAULT;                /* sstatus */
+
+    return (rt_uint8_t *)sp;
 }
 
 /*
@@ -98,7 +98,7 @@ void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to, rt_thread_t
     rt_interrupt_to_thread = to;
     rt_thread_switch_interrupt_flag = 1;
 
-    return ;
+    return;
 }
 #endif /* end of RT_USING_SMP */
 
@@ -117,6 +117,5 @@ void rt_hw_cpu_shutdown()
 
 void rt_hw_set_process_id(int pid)
 {
-    //TODO
+    // TODO
 }
-

+ 22 - 0
libcpu/risc-v/virt64/cpuport_gcc.S

@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2022-10-19     RT-Thread    the first version
+ */
+
+#include "cpuport.h"
+#include "stackframe.h"
+
+.global _rt_thread_entry
+_rt_thread_entry:
+    LOAD    ra, (sp)    /* texit */
+    addi    sp, sp, 8
+    LOAD    a0, (sp)    /* parameter */
+    addi    sp, sp, 8
+    LOAD    t0, (sp)    /* tentry */
+    addi    sp, sp, 8
+    jr      t0

+ 9 - 16
libcpu/risc-v/virt64/interrupt_gcc.S

@@ -11,7 +11,6 @@
  * 2021/12/24     JasonHu      Add user setting save/restore
  */
 
-#define __ASSEMBLY__
 #include "cpuport.h"
 #include "encoding.h"
 #include "stackframe.h"
@@ -28,7 +27,7 @@ trap_entry:
     la sp, __stack_cpu0
     //backup context
     SAVE_ALL
-    
+
     RESTORE_SYS_GP
 
     //check syscall
@@ -50,7 +49,6 @@ trap_entry:
     beqz  s2, spurious_interrupt
     sw    zero, 0(s0)
 
-.global rt_hw_context_switch_interrupt_do
 rt_hw_context_switch_interrupt_do:
 
 //swap to thread kernel stack
@@ -85,19 +83,14 @@ copy_context_loop_interrupt:
     addi t2, t2, 8
     bnez s0, copy_context_loop_interrupt
 
-    la    s0, rt_interrupt_from_thread
-    LOAD  s1, 0(s0)
-    STORE sp, 0(s1)
-
-    la    s0, rt_interrupt_to_thread
-    LOAD  s1, 0(s0)
-    LOAD  sp, 0(s1)
-
-    #ifdef RT_USING_USERSPACE
-        mv a0, s1
-        jal rt_thread_sp_to_thread
-        jal lwp_mmu_switch
-    #endif
+do_ctx_switch:
+    la    t0, rt_interrupt_from_thread
+    LOAD  a0, 0(t0)
+
+    la    t0, rt_interrupt_to_thread
+    LOAD  a1, 0(t0)
+
+    jal     rt_hw_context_switch
 
 spurious_interrupt:
     LOAD t0, 2 * REGBYTES(sp)

+ 2 - 2
libcpu/risc-v/virt64/riscv_mmu.c

@@ -30,10 +30,10 @@ void mmu_set_pagetable(rt_ubase_t addr)
 
 void mmu_enable_user_page_access()
 {
-    set_csr(sstatus, SSTATUS_PUM);
+    set_csr(sstatus, SSTATUS_SUM);
 }
 
 void mmu_disable_user_page_access()
 {
-    clear_csr(sstatus, SSTATUS_PUM);
+    clear_csr(sstatus, SSTATUS_SUM);
 }

+ 0 - 1
libcpu/risc-v/virt64/startup_gcc.S

@@ -11,7 +11,6 @@
  */
 
 #define SSTATUS_FS      0x00006000U /* initial state of FPU, clear to disable */
-#define __ASSEMBLY__
 #include <cpuport.h>
 
 boot_hartid: .int

+ 1 - 1
libcpu/risc-v/virt64/trap.c

@@ -45,7 +45,7 @@ void dump_regs(struct rt_hw_stack_frame *regs)
     rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SIE) ? "Supervisor Interrupt Enabled" : "Supervisor Interrupt Disabled");
     rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SPIE) ? "Last Time Supervisor Interrupt Enabled" : "Last Time Supervisor Interrupt Disabled");
     rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SPP) ? "Last Privilege is Supervisor Mode" : "Last Privilege is User Mode");
-    rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_PUM) ? "Permit to Access User Page" : "Not Permit to Access User Page");
+    rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SUM) ? "Permit to Access User Page" : "Not Permit to Access User Page");
     rt_kprintf("\t%s\n", (regs->sstatus & (1 << 19)) ? "Permit to Read Executable-only Page" : "Not Permit to Read Executable-only Page");
     rt_size_t satp_v = read_csr(satp);
     rt_kprintf("satp = 0x%p\n", satp_v);