diff options
author | br <br@FreeBSD.org> | 2016-02-04 12:49:28 +0000 |
---|---|---|
committer | br <br@FreeBSD.org> | 2016-02-04 12:49:28 +0000 |
commit | a6a53aa0dc541d11f006058c210249628072c55e (patch) | |
tree | 9073a5444f815c7ecf68e5e2f15d95513f9cfc4c /sys/riscv | |
parent | 444874ded476cb85cea4f20deced485f0aabf91c (diff) | |
download | FreeBSD-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.h | 7 | ||||
-rw-r--r-- | sys/riscv/riscv/exception.S | 17 | ||||
-rw-r--r-- | sys/riscv/riscv/genassym.c | 1 | ||||
-rw-r--r-- | sys/riscv/riscv/machdep.c | 11 | ||||
-rw-r--r-- | sys/riscv/riscv/swtch.S | 23 | ||||
-rw-r--r-- | sys/riscv/riscv/vm_machdep.c | 2 |
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 |