Push loading curthread into assembly in the synchronous exception handlers.
This will help investigating the performance impact of moving parts of the switch statement in do_el0_sync into assembly. Sponsored by: DARPA, AFRL
This commit is contained in:
parent
21ce594e7a
commit
d7635c7a49
@ -143,7 +143,8 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
ENTRY(handle_el1h_sync)
|
||||
save_registers 1
|
||||
mov x0, sp
|
||||
ldr x0, [x18, #PC_CURTHREAD]
|
||||
mov x1, sp
|
||||
bl do_el1h_sync
|
||||
restore_registers 1
|
||||
eret
|
||||
@ -163,7 +164,9 @@ END(handle_el1h_error)
|
||||
|
||||
ENTRY(handle_el0_sync)
|
||||
save_registers 0
|
||||
mov x0, sp
|
||||
ldr x0, [x18, #PC_CURTHREAD]
|
||||
mov x1, sp
|
||||
str x1, [x0, #TD_FRAME]
|
||||
bl do_el0_sync
|
||||
do_ast
|
||||
restore_registers 0
|
||||
|
@ -57,6 +57,7 @@ ASSYM(SF_UC, offsetof(struct sigframe, sf_uc));
|
||||
|
||||
ASSYM(TD_PCB, offsetof(struct thread, td_pcb));
|
||||
ASSYM(TD_FLAGS, offsetof(struct thread, td_flags));
|
||||
ASSYM(TD_FRAME, offsetof(struct thread, td_frame));
|
||||
ASSYM(TD_LOCK, offsetof(struct thread, td_lock));
|
||||
|
||||
ASSYM(TF_SIZE, sizeof(struct trapframe));
|
||||
|
@ -72,8 +72,8 @@ __FBSDID("$FreeBSD$");
|
||||
extern register_t fsu_intr_fault;
|
||||
|
||||
/* Called from exception.S */
|
||||
void do_el1h_sync(struct trapframe *);
|
||||
void do_el0_sync(struct trapframe *);
|
||||
void do_el1h_sync(struct thread *, struct trapframe *);
|
||||
void do_el0_sync(struct thread *, struct trapframe *);
|
||||
void do_el0_error(struct trapframe *);
|
||||
static void print_registers(struct trapframe *frame);
|
||||
|
||||
@ -130,23 +130,20 @@ cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
|
||||
#include "../../kern/subr_syscall.c"
|
||||
|
||||
static void
|
||||
svc_handler(struct trapframe *frame)
|
||||
svc_handler(struct thread *td, struct trapframe *frame)
|
||||
{
|
||||
struct syscall_args sa;
|
||||
struct thread *td;
|
||||
int error;
|
||||
|
||||
td = curthread;
|
||||
|
||||
error = syscallenter(td, &sa);
|
||||
syscallret(td, error, &sa);
|
||||
}
|
||||
|
||||
static void
|
||||
data_abort(struct trapframe *frame, uint64_t esr, uint64_t far, int lower)
|
||||
data_abort(struct thread *td, struct trapframe *frame, uint64_t esr,
|
||||
uint64_t far, int lower)
|
||||
{
|
||||
struct vm_map *map;
|
||||
struct thread *td;
|
||||
struct proc *p;
|
||||
struct pcb *pcb;
|
||||
vm_prot_t ftype;
|
||||
@ -167,7 +164,6 @@ data_abort(struct trapframe *frame, uint64_t esr, uint64_t far, int lower)
|
||||
}
|
||||
#endif
|
||||
|
||||
td = curthread;
|
||||
pcb = td->td_pcb;
|
||||
|
||||
/*
|
||||
@ -261,7 +257,7 @@ print_registers(struct trapframe *frame)
|
||||
}
|
||||
|
||||
void
|
||||
do_el1h_sync(struct trapframe *frame)
|
||||
do_el1h_sync(struct thread *td, struct trapframe *frame)
|
||||
{
|
||||
uint32_t exception;
|
||||
uint64_t esr, far;
|
||||
@ -276,14 +272,14 @@ do_el1h_sync(struct trapframe *frame)
|
||||
#endif
|
||||
|
||||
CTR4(KTR_TRAP,
|
||||
"do_el1_sync: curthread: %p, esr %lx, elr: %lx, frame: %p",
|
||||
curthread, esr, frame->tf_elr, frame);
|
||||
"do_el1_sync: curthread: %p, esr %lx, elr: %lx, frame: %p", td,
|
||||
esr, frame->tf_elr, frame);
|
||||
|
||||
switch(exception) {
|
||||
case EXCP_FP_SIMD:
|
||||
case EXCP_TRAP_FP:
|
||||
#ifdef VFP
|
||||
if ((curthread->td_pcb->pcb_fpflags & PCB_FP_KERN) != 0) {
|
||||
if ((td->td_pcb->pcb_fpflags & PCB_FP_KERN) != 0) {
|
||||
vfp_restore_state();
|
||||
} else
|
||||
#endif
|
||||
@ -297,7 +293,7 @@ do_el1h_sync(struct trapframe *frame)
|
||||
case EXCP_DATA_ABORT:
|
||||
far = READ_SPECIALREG(far_el1);
|
||||
intr_enable();
|
||||
data_abort(frame, esr, far, 0);
|
||||
data_abort(td, frame, esr, far, 0);
|
||||
break;
|
||||
case EXCP_BRK:
|
||||
#ifdef KDTRACE_HOOKS
|
||||
@ -338,9 +334,8 @@ el0_excp_unknown(struct trapframe *frame, uint64_t far)
|
||||
}
|
||||
|
||||
void
|
||||
do_el0_sync(struct trapframe *frame)
|
||||
do_el0_sync(struct thread *td, struct trapframe *frame)
|
||||
{
|
||||
struct thread *td;
|
||||
uint32_t exception;
|
||||
uint64_t esr, far;
|
||||
|
||||
@ -349,9 +344,6 @@ do_el0_sync(struct trapframe *frame)
|
||||
("Invalid pcpu address from userland: %p (tpidr %lx)",
|
||||
get_pcpu(), READ_SPECIALREG(tpidr_el1)));
|
||||
|
||||
td = curthread;
|
||||
td->td_frame = frame;
|
||||
|
||||
esr = frame->tf_esr;
|
||||
exception = ESR_ELx_EXCEPTION(esr);
|
||||
switch (exception) {
|
||||
@ -364,8 +356,8 @@ do_el0_sync(struct trapframe *frame)
|
||||
intr_enable();
|
||||
|
||||
CTR4(KTR_TRAP,
|
||||
"do_el0_sync: curthread: %p, esr %lx, elr: %lx, frame: %p",
|
||||
curthread, esr, frame->tf_elr, frame);
|
||||
"do_el0_sync: curthread: %p, esr %lx, elr: %lx, frame: %p", td, esr,
|
||||
frame->tf_elr, frame);
|
||||
|
||||
switch(exception) {
|
||||
case EXCP_FP_SIMD:
|
||||
@ -377,12 +369,12 @@ do_el0_sync(struct trapframe *frame)
|
||||
#endif
|
||||
break;
|
||||
case EXCP_SVC:
|
||||
svc_handler(frame);
|
||||
svc_handler(td, frame);
|
||||
break;
|
||||
case EXCP_INSN_ABORT_L:
|
||||
case EXCP_DATA_ABORT_L:
|
||||
case EXCP_DATA_ABORT:
|
||||
data_abort(frame, esr, far, 1);
|
||||
data_abort(td, frame, esr, far, 1);
|
||||
break;
|
||||
case EXCP_UNKNOWN:
|
||||
el0_excp_unknown(frame, far);
|
||||
@ -418,10 +410,10 @@ do_el0_sync(struct trapframe *frame)
|
||||
break;
|
||||
}
|
||||
|
||||
KASSERT((curthread->td_pcb->pcb_fpflags & ~PCB_FP_USERMASK) == 0,
|
||||
KASSERT((td->td_pcb->pcb_fpflags & ~PCB_FP_USERMASK) == 0,
|
||||
("Kernel VFP flags set while entering userspace"));
|
||||
KASSERT(
|
||||
curthread->td_pcb->pcb_fpusaved == &curthread->td_pcb->pcb_fpustate,
|
||||
td->td_pcb->pcb_fpusaved == &td->td_pcb->pcb_fpustate,
|
||||
("Kernel VFP state in use when entering userspace"));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user