The standard RISC-V calling convention says that the stack pointer
should be 16-byte aligned.
The patch below corrects the alignment of the kernel stack in context
switching and exception handling.
OK?
The diff reveals that curcpu is stored in an unnamed spot near the upper
end of u-area when running in user mode. Should struct trapframe contain
a field where curcpu is stored, so that the usage would become more
apparent? I guess the pointer could also be stored in one of the
existing fields with an appropriate comment in the struct definition.
Index: arch/riscv64/include/param.h
===================================================================
RCS file: src/sys/arch/riscv64/include/param.h,v
retrieving revision 1.4
diff -u -p -r1.4 param.h
--- arch/riscv64/include/param.h 16 Jun 2021 12:00:15 -0000 1.4
+++ arch/riscv64/include/param.h 22 Feb 2022 15:29:05 -0000
@@ -75,6 +75,7 @@
#define STACKALIGNBYTES (16 - 1)
#define STACKALIGN(p) ((u_long)(p) &~ STACKALIGNBYTES)
+#define FRAMESZ(sz) (((sz) + STACKALIGNBYTES) &
~STACKALIGNBYTES)
#define __HAVE_FDT
Index: arch/riscv64/riscv64/cpuswitch.S
===================================================================
RCS file: src/sys/arch/riscv64/riscv64/cpuswitch.S,v
retrieving revision 1.6
diff -u -p -r1.6 cpuswitch.S
--- arch/riscv64/riscv64/cpuswitch.S 22 Feb 2022 07:47:46 -0000 1.6
+++ arch/riscv64/riscv64/cpuswitch.S 22 Feb 2022 15:29:05 -0000
@@ -17,8 +17,9 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include "machine/asm.h"
#include "assym.h"
+#include <machine/asm.h>
+#include <machine/param.h>
/*
* cpu_switchto(struct proc *oldproc, struct proc *newproc)
@@ -30,7 +31,7 @@ ENTRY(cpu_switchto_asm)
beqz a0, 1f
// create switchframe
- addi sp, sp, -SWITCHFRAME_SIZEOF
+ addi sp, sp, -FRAMESZ(SWITCHFRAME_SIZEOF)
sd s0, (SF_S + 0 * 8)(sp)
sd s1, (SF_S + 1 * 8)(sp)
sd s2, (SF_S + 2 * 8)(sp)
@@ -86,7 +87,7 @@ ENTRY(cpu_switchto_asm)
ld ra, SF_RA(sp)
RETGUARD_CALC_COOKIE(a7)
- addi sp, sp, SWITCHFRAME_SIZEOF
+ addi sp, sp, FRAMESZ(SWITCHFRAME_SIZEOF)
RETGUARD_CHECK(cpu_switchto, a7)
ret
END(cpu_switch_asm)
Index: arch/riscv64/riscv64/exception.S
===================================================================
RCS file: src/sys/arch/riscv64/riscv64/exception.S,v
retrieving revision 1.5
diff -u -p -r1.5 exception.S
--- arch/riscv64/riscv64/exception.S 20 May 2021 04:22:33 -0000 1.5
+++ arch/riscv64/riscv64/exception.S 22 Feb 2022 15:29:05 -0000
@@ -36,11 +36,12 @@
#include "assym.h"
#include <machine/asm.h>
+#include <machine/param.h>
#include <machine/trap.h>
#include <machine/riscvreg.h>
.macro save_registers mode
- addi sp, sp, -(TRAPFRAME_SIZEOF)
+ addi sp, sp, -FRAMESZ(TRAPFRAME_SIZEOF)
sd ra, (TF_RA)(sp)
@@ -54,7 +55,7 @@
/* Load our pcpu */
sd tp, (TF_TP)(sp)
- ld tp, (TRAPFRAME_SIZEOF)(sp)
+ ld tp, (FRAMESZ(TRAPFRAME_SIZEOF))(sp)
.endif
sd t0, (TF_T + 0 * 8)(sp)
@@ -89,7 +90,7 @@
.if \mode == 1
/* Store kernel sp */
- li t1, TRAPFRAME_SIZEOF
+ li t1, FRAMESZ(TRAPFRAME_SIZEOF)
add t0, sp, t1
sd t0, (TF_SP)(sp)
.else
@@ -142,7 +143,7 @@
csrw sscratch, t0
/* Store our pcpu */
- sd tp, (TRAPFRAME_SIZEOF)(sp)
+ sd tp, (FRAMESZ(TRAPFRAME_SIZEOF))(sp)
ld tp, (TF_TP)(sp)
/* And restore the user's global pointer */
@@ -181,7 +182,7 @@
ld a6, (TF_A + 6 * 8)(sp)
ld a7, (TF_A + 7 * 8)(sp)
- addi sp, sp, (TRAPFRAME_SIZEOF)
+ addi sp, sp, FRAMESZ(TRAPFRAME_SIZEOF)
.endm
.macro do_ast
Index: arch/riscv64/riscv64/vm_machdep.c
===================================================================
RCS file: src/sys/arch/riscv64/riscv64/vm_machdep.c,v
retrieving revision 1.8
diff -u -p -r1.8 vm_machdep.c
--- arch/riscv64/riscv64/vm_machdep.c 22 Feb 2022 07:47:46 -0000 1.8
+++ arch/riscv64/riscv64/vm_machdep.c 22 Feb 2022 15:29:05 -0000
@@ -91,7 +91,8 @@ cpu_fork(struct proc *p1, struct proc *p
tf->tf_sstatus |= (SSTATUS_SPIE); /* Enable interrupts. */
tf->tf_sstatus &= ~(SSTATUS_SPP); /* Enter user mode. */
- sf = (struct switchframe *)tf - 1;
+ sf = (struct switchframe *)STACKALIGN((u_long)tf
+ - sizeof(struct switchframe));
sf->sf_s[0] = 0; /* Terminate chain of call frames. */
sf->sf_s[1] = (uint64_t)func;
sf->sf_s[2] = (uint64_t)arg;