summaryrefslogtreecommitdiffstats
path: root/sys/riscv
diff options
context:
space:
mode:
authorbr <br@FreeBSD.org>2016-02-04 12:49:28 +0000
committerbr <br@FreeBSD.org>2016-02-04 12:49:28 +0000
commita6a53aa0dc541d11f006058c210249628072c55e (patch)
tree9073a5444f815c7ecf68e5e2f15d95513f9cfc4c /sys/riscv
parent444874ded476cb85cea4f20deced485f0aabf91c (diff)
downloadFreeBSD-src-a6a53aa0dc541d11f006058c210249628072c55e.zip
FreeBSD-src-a6a53aa0dc541d11f006058c210249628072c55e.tar.gz
Reuse gp register for pcpu pointer.
gp (global pointer) is used by compiler in userland only, so re-use it for pcpup in kernel, save it on stack on switching out to userland and load back on return to kernel. Discussed with: jhb, andrew, kib Sponsored by: DARPA, AFRL Sponsored by: HEIF5 Differential Revision: https://reviews.freebsd.org/D5178
Diffstat (limited to 'sys/riscv')
-rw-r--r--sys/riscv/include/pcpu.h7
-rw-r--r--sys/riscv/riscv/exception.S17
-rw-r--r--sys/riscv/riscv/genassym.c1
-rw-r--r--sys/riscv/riscv/machdep.c11
-rw-r--r--sys/riscv/riscv/swtch.S23
-rw-r--r--sys/riscv/riscv/vm_machdep.c2
6 files changed, 38 insertions, 23 deletions
diff --git a/sys/riscv/include/pcpu.h b/sys/riscv/include/pcpu.h
index c60a954..7dfe23d 100644
--- a/sys/riscv/include/pcpu.h
+++ b/sys/riscv/include/pcpu.h
@@ -47,8 +47,11 @@ extern struct pcpu *pcpup;
static inline struct pcpu *
get_pcpu(void)
{
+ struct pcpu *pcpu;
- return (pcpup);
+ __asm __volatile("mv %0, gp" : "=&r"(pcpu));
+
+ return (pcpu);
}
static inline struct thread *
@@ -56,7 +59,7 @@ get_curthread(void)
{
struct thread *td;
- td = (struct thread *)*(uint64_t *)pcpup;
+ __asm __volatile("ld %0, 0(gp)" : "=&r"(td));
return (td);
}
diff --git a/sys/riscv/riscv/exception.S b/sys/riscv/riscv/exception.S
index 07fcfc5..8bd9027 100644
--- a/sys/riscv/riscv/exception.S
+++ b/sys/riscv/riscv/exception.S
@@ -41,12 +41,16 @@ __FBSDID("$FreeBSD$");
#include <machine/riscvreg.h>
.macro save_registers el
- addi sp, sp, -280
+ addi sp, sp, -(TF_SIZE)
sd ra, (TF_RA)(sp)
- sd gp, (TF_GP)(sp)
sd tp, (TF_TP)(sp)
+.if \el == 0 /* We came from userspace. Load our pcpu */
+ sd gp, (TF_GP)(sp)
+ ld gp, (TF_SIZE)(sp)
+.endif
+
sd t0, (TF_T + 0 * 8)(sp)
sd t1, (TF_T + 1 * 8)(sp)
sd t2, (TF_T + 2 * 8)(sp)
@@ -127,13 +131,16 @@ __FBSDID("$FreeBSD$");
csrw sepc, t0
.if \el == 0
- /* Load user sp */
+ /* We go to userspace. Load user sp */
ld t0, (TF_SP)(sp)
csrw sscratch, t0
+
+ /* And store our pcpu */
+ sd gp, (TF_SIZE)(sp)
+ ld gp, (TF_GP)(sp)
.endif
ld ra, (TF_RA)(sp)
- ld gp, (TF_GP)(sp)
ld tp, (TF_TP)(sp)
ld t0, (TF_T + 0 * 8)(sp)
@@ -166,7 +173,7 @@ __FBSDID("$FreeBSD$");
ld a6, (TF_A + 6 * 8)(sp)
ld a7, (TF_A + 7 * 8)(sp)
- addi sp, sp, 280
+ addi sp, sp, (TF_SIZE)
.endm
.macro do_ast
diff --git a/sys/riscv/riscv/genassym.c b/sys/riscv/riscv/genassym.c
index f5c971d..bf6c8fb 100644
--- a/sys/riscv/riscv/genassym.c
+++ b/sys/riscv/riscv/genassym.c
@@ -85,6 +85,7 @@ ASSYM(TD_FRAME, offsetof(struct thread, td_frame));
ASSYM(TD_MD, offsetof(struct thread, td_md));
ASSYM(TD_LOCK, offsetof(struct thread, td_lock));
+ASSYM(TF_SIZE, sizeof(struct trapframe));
ASSYM(TF_RA, offsetof(struct trapframe, tf_ra));
ASSYM(TF_SP, offsetof(struct trapframe, tf_sp));
ASSYM(TF_GP, offsetof(struct trapframe, tf_gp));
diff --git a/sys/riscv/riscv/machdep.c b/sys/riscv/riscv/machdep.c
index 5f9bd1f..79688e6 100644
--- a/sys/riscv/riscv/machdep.c
+++ b/sys/riscv/riscv/machdep.c
@@ -256,7 +256,9 @@ ptrace_clear_single_step(struct thread *td)
void
exec_setregs(struct thread *td, struct image_params *imgp, u_long stack)
{
- struct trapframe *tf = td->td_frame;
+ struct trapframe *tf;
+
+ tf = td->td_frame;
memset(tf, 0, sizeof(struct trapframe));
@@ -563,6 +565,7 @@ sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
static void
init_proc0(vm_offset_t kstack)
{
+
pcpup = &__pcpu[0];
proc_linkup0(&proc0, &thread0);
@@ -760,11 +763,7 @@ initriscv(struct riscv_bootparams *rvbp)
pcpu_init(pcpup, 0, sizeof(struct pcpu));
/* Set the pcpu pointer */
-#if 0
- /* SMP TODO: try re-use gp for pcpu pointer */
- __asm __volatile(
- "mv gp, %0" :: "r"(pcpup));
-#endif
+ __asm __volatile("mv gp, %0" :: "r"(pcpup));
PCPU_SET(curthread, &thread0);
diff --git a/sys/riscv/riscv/swtch.S b/sys/riscv/riscv/swtch.S
index 945fce3..5e9b3c9 100644
--- a/sys/riscv/riscv/swtch.S
+++ b/sys/riscv/riscv/swtch.S
@@ -74,8 +74,6 @@ ENTRY(cpu_throw)
/* Load registers */
ld ra, (PCB_RA)(x13)
ld sp, (PCB_SP)(x13)
- ld gp, (PCB_GP)(x13)
- ld tp, (PCB_TP)(x13)
/* s[0-11] */
ld s0, (PCB_S + 0 * 8)(x13)
@@ -120,8 +118,6 @@ ENTRY(cpu_switch)
/* Store the callee-saved registers */
sd ra, (PCB_RA)(x13)
sd sp, (PCB_SP)(x13)
- sd gp, (PCB_GP)(x13)
- sd tp, (PCB_TP)(x13)
/* We use these in fork_trampoline */
sd t0, (PCB_T + 0 * 8)(x13)
@@ -176,8 +172,6 @@ ENTRY(cpu_switch)
/* Restore the registers */
ld ra, (PCB_RA)(x13)
ld sp, (PCB_SP)(x13)
- ld gp, (PCB_GP)(x13)
- ld tp, (PCB_TP)(x13)
/* We use these in fork_trampoline */
ld t0, (PCB_T + 0 * 8)(x13)
@@ -254,12 +248,23 @@ ENTRY(fork_trampoline)
ld a6, (TF_A + 6 * 8)(sp)
ld a7, (TF_A + 7 * 8)(sp)
+ /* Load user ra and sp */
+ ld tp, (TF_TP)(sp)
+ ld ra, (TF_RA)(sp)
+
+ /*
+ * Store our pcpup on stack, we will load it back
+ * on kernel mode trap.
+ */
+ sd gp, (TF_SIZE)(sp)
+ ld gp, (TF_GP)(sp)
+
/* Save kernel stack so we can use it doing a user trap */
+ addi sp, sp, TF_SIZE
csrw sscratch, sp
- /* Load user ra and sp */
- ld ra, (TF_RA)(sp)
- ld sp, (TF_SP)(sp)
+ /* Load user stack */
+ ld sp, (TF_SP - TF_SIZE)(sp)
eret
END(fork_trampoline)
diff --git a/sys/riscv/riscv/vm_machdep.c b/sys/riscv/riscv/vm_machdep.c
index 0f65250..fef626b 100644
--- a/sys/riscv/riscv/vm_machdep.c
+++ b/sys/riscv/riscv/vm_machdep.c
@@ -218,7 +218,7 @@ 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(
- td->td_pcb - 1);
+ (caddr_t)td->td_pcb - 8 - sizeof(struct trapframe));
}
void
OpenPOWER on IntegriCloud