xiaoxiang781216 commented on pull request #5782:
URL: https://github.com/apache/incubator-nuttx/pull/5782#issuecomment-1076644915


   > > > > S-mode can hook ECALL to self, @pussuw could you explain more why we 
need handle differently in S-mode and M-mode?
   > > > 
   > > > 
   > > > S-mode can trap ecall from user mode (U-mode) but not from S-mode. So 
ecall from S-mode to S-mode is not possible.
   > > 
   > > 
   > > Ok, I get the key point. So is syscall from S-mode to S-mode only used 
for kernel thread context switch?
   > 
   > A context switch can occur in two ways:
   > 
   > 1. A process running thread in privileged mode (either kernel process or 
user process who's privileges are temporary raised e.g. when executing a system 
call from usersace), in this case a context switch occurs via 
`riscv_switchcontext`. In flat mode (M-mode) this is handled via:
   > 
   > ```
   > #define riscv_switchcontext(saveregs, restoreregs) \
   >   sys_call2(SYS_switch_context, (uintptr_t)saveregs, 
(uintptr_t)restoreregs)
   > ```
   > 
   > Which uses ecall to enter the trap handler which does all the work. This 
works, because ecall from M-mode to M-mode enters M-mode.
   > 
   > This cannot be used to switch context in S-mode, because it would raise 
privileges to M-mode (ecall from S-mode) which is not what we want.
   
   How about we trigger software interrupt(SSIP) instead ECALL?
   
   > Instead, the assembly routine below is used to do the same work as was 
done by the trap handler previously!
   > 
   > ```
   > riscv_switchcontext:
   > 
   >   /* Save old context to arg[0] */
   > 
   >   save_ctx   a0                        /* save context */
   > 
   >   REGSTORE   x1, REG_EPC(a0)           /* save ra to epc */
   >   REGSTORE   sp, REG_SP(a0)            /* original SP */
   > 
   >   /* Set previous privilege, we are in privileged mode now */
   > 
   >   csrr       s0, CSR_STATUS            /* read status register */
   >   li         s1, STATUS_PPP            /* set previous privilege */
   >   or         s0, s0, s1
   >   li         s1, ~STATUS_PIE           /* clear previous interrupt enable 
*/
   >   and        s0, s0, s1
   >   REGSTORE   s0, REG_INT_CTX(a0)       /* store status to context */
   > 
   > #ifdef CONFIG_ARCH_FPU
   >   jal        x1, riscv_savefpu         /* FP registers */
   > #endif
   > 
   >   /* Load new context from arg[1] */
   > 
   >   mv         a0, a1                    /* load from a1 */
   >   j          riscv_fullcontextrestore  /* restore context */
   > ```
   > 
   
   Can we fake CPU by modifying CSR_STATUS to match the ECALL condition and 
ghen jump to exception_common directly?
   
   > 2. The second way a context switch can occur is in the trap handler 
itself, for example if a task is waiting for uart semaphore and the semaphore 
is posted by the uart interrupt handler, this can dispatch a wake up signal to 
the task, and the task that was running prior to taking the trap gets preempted 
and the task that was waiting for the semaphore gets activated instead.
   > 
   
   It's different from the active context switch, the passive context 
switch(e.g. the block thread wake up by an interrupt handler) since the 
interrupt handle already run in S-mode:
   
   1. The exception entry pointer already save the current thread context for us
   2. So we can restore the unblock thread context directly without trap to 
M-mode
   
   > > > Also, we want to use ecall in S-mode to raise privileges to M-mode, to 
access some machine mode services (mhartid,
   > > 
   > > 
   > > Yes, but it's still the same ecall instruction. Here is my understanding:
   > > ```
   > > 1. Any syscall(include context switch) issued by U-mode could be 
implemented by ECALL and raise to S-mode
   > > ```
   > 
   > A user task will never call syscall(SYS_context_switch), or any of the 
reserved SYS_ call numbers, **from user mode**. If a user task calls for a 
context switch, it means its privileges are raised to kernel temporarily.
   
   My understanding is different from yours: user task need issue syscall here 
otherwise how the thread can raise the privilege to S-mode? 
   
   > The reserved syscalls are reserved for the kernel only and thus will only 
be executed by privileged mode code, i.e. only the kernel does this.
   
   No, all syscalls(either reserved or normal) are for user space(U-mode) to 
initiate the designed functionality to kernel space.
   
   > 
   > A user task can however call e.g. sys_call(SYS__exit, ...), which is 
executed via a proxy function like this:
   > 
   > ```
   > void _exit(int parm1)
   > {
   >   (void)sys_call1((unsigned int)SYS__exit, (uintptr_t)parm1);
   >   while(1);
   > }
   > ```
   > 
   > This sys_call will come from U-mode and it is intended to raise the 
privilege level to privileged mode.
   > 
   > Vica versa, a task running in kernel mode (be it a user task or a kernel 
task, what I mean the current privilege level = kernel) will **never** execute 
any of the old sys_call0-6 functions. They are not needed! The only reason the 
prototypes / definitions exist, is because the proxy functions mentioned above 
need their definitions, due to how the build system creates PROXY_ and STUB_ 
function into the /syscall/proxies and /syscall/stubs folders in non-flat 
builds.
   
   Yes, I agree the behavior your describe above.
   
   > We could just as well move the sys_call0-6 prototypes and definitions to 
the libc folder, under machine/risc-v IMO.
   > 
   
   The suggestion look reasonable, sys_call0-6 is directly called by user space 
code, libc/machine is a better place. But, we can do the change for all arch in 
a new patch.
   
   > In flat builds this will obviously fail horribly, and this is one of the 
reasons why kernel in S-mode is not really feasible for the flat build (among 
other things, like PMP needs to be configured to give access to memory and so 
forth).
   > 
   
   Yes, I agree too. It's better to run flat mode in M-mode.
   
   > > ```
   > > 2. Kernel thread context switch could be implemented by ECALL too, but 
it will be handled in M-mode instead S-mode
   > > ```
   > 
   > I don't know how to do this, M-mode does not support address translations, 
so when using address environments (the kernel memory is MMU mapped) it will 
become quite difficult.
   
   Sorry, I forget this. Yes, it's very hard to access the memory pointed by 
S-mode. It's clear that it isn't a good idea to handle S-mode context switch in 
M-mode.
   
   > 
   > > ```
   > > 3. Some special function(e.g. mhartid) which need the highest privilege 
has to issue ECALL from S-mode to M-mode
   > > ```
   > 
   > Yes, exactly
   > 
   > > So, I think we can still use the same sys_call0-syscall6 as before, and:
   > > ```
   > > 1. Handle U-mode syscall in S-mode as before
   > > ```
   > 
   > Yes, this is why we need sys_call0-6, for the userspace
   > 
   > > ```
   > > 2. Handle S-mode context switch in M-mode( the code should be same as 
S-mode)
   > > ```
   > 
   > I don't know how to do this
   > 
   > > ```
   > > 3. Extend the reserved syscall id to cover the special need(e.g. mhardid)
   > > ```
   > 
   > Can be done, but I'd like to keep this separate. What riscv_mcall.c 
basically implements is a tiny SBI (comparable to openSBI for example but much 
smaller).
   > 
   > > > mtimer to name a few, see riscv_mcall.c).
   > > 
   > > 
   > > Why we can't use S-mode timer instead?
   > 
   > There is no S-mode timer as far as I know. There is a scounter but this is 
for performance monitoring / profiling as far as I know. What we need is a 
ticker with a compare match event, i.e. mtime and mtimecmp. Such memory mapped 
registers are not available for S-mode.
   
   Ok, it just has the S-mode timer interrupt pending bit(STIP), so we have:
   
   1. Let M-mode simulate the software timer and access the functionality 
through ECALL and trigger the interrupt by STIP
   2. Use the external hardware time instead
   
   To support cpuid and timer, S-mode has to talk with M-mode. How do you 
reduce the coupling since we can't assume M-mode is also running NuttX? Do you 
plan reuse OpenSBI interface?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscr...@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


Reply via email to