Page MenuHomeFreeBSD

D48799.diff
No OneTemporary

D48799.diff

diff --git a/sys/riscv/include/frame.h b/sys/riscv/include/frame.h
--- a/sys/riscv/include/frame.h
+++ b/sys/riscv/include/frame.h
@@ -57,6 +57,10 @@
uint64_t tf_scause;
};
+#ifdef _KERNEL
+#define TF_SIZE (roundup2(sizeof(struct trapframe), STACKALIGNBYTES + 1))
+#endif
+
/*
* Signal frame. Pushed onto user stack before calling sigcode.
*/
@@ -65,6 +69,16 @@
ucontext_t sf_uc; /* actual saved ucontext */
};
+#ifdef _KERNEL
+/*
+ * Kernel frame. Reserved near the top of kernel stacks for saving kernel
+ * state while in userspace.
+ */
+struct kernframe {
+ register_t kf_tp;
+};
+#endif
+
#endif /* !LOCORE */
/* Definitions for syscalls */
diff --git a/sys/riscv/riscv/exception.S b/sys/riscv/riscv/exception.S
--- a/sys/riscv/riscv/exception.S
+++ b/sys/riscv/riscv/exception.S
@@ -53,7 +53,7 @@
.option pop
/* Load our pcpu */
- ld tp, (TF_SIZE)(sp)
+ ld tp, (TF_SIZE + KF_TP)(sp)
.endif
sd t0, (TF_T + 0 * 8)(sp)
@@ -139,7 +139,7 @@
csrw sscratch, t0
/* Store our pcpu */
- sd tp, (TF_SIZE)(sp)
+ sd tp, (TF_SIZE + KF_TP)(sp)
ld tp, (TF_TP)(sp)
/* And restore the user's global pointer */
diff --git a/sys/riscv/riscv/genassym.c b/sys/riscv/riscv/genassym.c
--- a/sys/riscv/riscv/genassym.c
+++ b/sys/riscv/riscv/genassym.c
@@ -85,7 +85,7 @@
ASSYM(TD_MD, offsetof(struct thread, td_md));
ASSYM(TD_LOCK, offsetof(struct thread, td_lock));
-ASSYM(TF_SIZE, roundup2(sizeof(struct trapframe), STACKALIGNBYTES + 1));
+ASSYM(TF_SIZE, TF_SIZE);
ASSYM(TF_RA, offsetof(struct trapframe, tf_ra));
ASSYM(TF_SP, offsetof(struct trapframe, tf_sp));
ASSYM(TF_GP, offsetof(struct trapframe, tf_gp));
@@ -98,6 +98,8 @@
ASSYM(TF_SCAUSE, offsetof(struct trapframe, tf_scause));
ASSYM(TF_SSTATUS, offsetof(struct trapframe, tf_sstatus));
+ASSYM(KF_TP, offsetof(struct kernframe, kf_tp));
+
ASSYM(HYP_H_RA, offsetof(struct hypctx, host_regs.hyp_ra));
ASSYM(HYP_H_SP, offsetof(struct hypctx, host_regs.hyp_sp));
ASSYM(HYP_H_GP, offsetof(struct hypctx, host_regs.hyp_gp));
diff --git a/sys/riscv/riscv/swtch.S b/sys/riscv/riscv/swtch.S
--- a/sys/riscv/riscv/swtch.S
+++ b/sys/riscv/riscv/swtch.S
@@ -419,7 +419,7 @@
* Store our pcpup on stack, we will load it back
* on kernel mode trap.
*/
- sd tp, (TF_SIZE)(sp)
+ sd tp, (TF_SIZE + KF_TP)(sp)
ld tp, (TF_TP)(sp)
/* Save kernel stack so we can use it doing a user trap */
diff --git a/sys/riscv/riscv/vm_machdep.c b/sys/riscv/riscv/vm_machdep.c
--- a/sys/riscv/riscv/vm_machdep.c
+++ b/sys/riscv/riscv/vm_machdep.c
@@ -57,6 +57,26 @@
#define TP_OFFSET 16 /* sizeof(struct tcb) */
#endif
+static void
+cpu_set_pcb_frame(struct thread *td)
+{
+ td->td_pcb = (struct pcb *)((char *)td->td_kstack +
+ td->td_kstack_pages * PAGE_SIZE) - 1;
+
+ /*
+ * td->td_frame + TF_SIZE will be the saved kernel stack pointer whilst
+ * in userspace, so keep it aligned so it's also aligned when we
+ * subtract TF_SIZE in the trap handler (and here for the initial stack
+ * pointer). This also keeps the struct kernframe just afterwards
+ * aligned no matter what's in it or struct pcb.
+ *
+ * NB: TF_SIZE not sizeof(struct trapframe) as we need the rounded
+ * value to match the trap handler.
+ */
+ td->td_frame = (struct trapframe *)(STACKALIGN(
+ (char *)td->td_pcb - sizeof(struct kernframe)) - TF_SIZE);
+}
+
/*
* Finish a fork operation, with process p2 nearly set up.
* Copy and update the pcb, set up the stack so that the child
@@ -73,13 +93,12 @@
/* RISCVTODO: save the FPU state here */
- pcb2 = (struct pcb *)(td2->td_kstack +
- td2->td_kstack_pages * PAGE_SIZE) - 1;
+ cpu_set_pcb_frame(td2);
- td2->td_pcb = pcb2;
+ pcb2 = td2->td_pcb;
bcopy(td1->td_pcb, pcb2, sizeof(*pcb2));
- tf = (struct trapframe *)STACKALIGN((struct trapframe *)pcb2 - 1);
+ tf = td2->td_frame;
bcopy(td1->td_frame, tf, sizeof(*tf));
/* Clear syscall error flag */
@@ -91,8 +110,6 @@
tf->tf_sstatus |= (SSTATUS_SPIE); /* Enable interrupts. */
tf->tf_sstatus &= ~(SSTATUS_SPP); /* User mode. */
- td2->td_frame = tf;
-
/* Set the return value registers for fork() */
td2->td_pcb->pcb_s[0] = (uintptr_t)fork_return;
td2->td_pcb->pcb_s[1] = (uintptr_t)td2;
@@ -206,11 +223,7 @@
void
cpu_thread_alloc(struct thread *td)
{
-
- td->td_pcb = (struct pcb *)(td->td_kstack +
- td->td_kstack_pages * PAGE_SIZE) - 1;
- td->td_frame = (struct trapframe *)STACKALIGN(
- (caddr_t)td->td_pcb - 8 - sizeof(struct trapframe));
+ cpu_set_pcb_frame(td);
}
void

File Metadata

Mime Type
text/plain
Expires
Mon, Feb 10, 7:41 PM (7 h, 55 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16582606
Default Alt Text
D48799.diff (4 KB)

Event Timeline