Copy the syscall args in a tmp variable instead of directly using the

trapframe, as it can be modified in the syscall.
Call thread_user_enter() when appropriate.
This commit is contained in:
Olivier Houchard 2004-11-05 19:57:10 +00:00
parent 8ecf6f65d9
commit bd366a3cd4

View File

@ -215,7 +215,6 @@ data_abort_fixup(trapframe_t *tf, u_int fsr, u_int far, struct thread *td, struc
#endif /* CPU_ABORT_FIXUP_REQUIRED */
}
extern int curpid;
void
data_abort_handler(trapframe_t *tf)
{
@ -229,6 +228,8 @@ data_abort_handler(trapframe_t *tf)
u_int sticks = 0;
int error = 0;
struct ksig ksig;
struct proc *p;
/* Grab FAR/FSR before enabling interrupts */
far = cpu_faultaddress();
@ -244,13 +245,17 @@ data_abort_handler(trapframe_t *tf)
#endif
td = curthread;
p = td->td_proc;
/* Data abort came from user mode? */
user = TRAP_USERMODE(tf);
if (user) {
sticks = td->td_sticks; td->td_frame = tf;
if (td->td_ucred != td->td_proc->p_ucred)
cred_update_thread(td);
if (td->td_pflags & TDP_SA)
thread_user_enter(td);
}
/* Grab the current pcb */
@ -289,10 +294,6 @@ data_abort_handler(trapframe_t *tf)
return;
}
if (user) {
sticks = td->td_sticks;
td->td_frame = tf;
}
/*
* Make sure the Program Counter is sane. We could fall foul of
* someone executing Thumb code, in which case the PC might not
@ -408,6 +409,11 @@ data_abort_handler(trapframe_t *tf)
onfault = pcb->pcb_onfault;
pcb->pcb_onfault = NULL;
if (map != kernel_map) {
PROC_LOCK(p);
p->p_lock++;
PROC_UNLOCK(p);
}
error = vm_fault(map, va, ftype, (ftype & VM_PROT_WRITE) ?
VM_FAULT_DIRTY : VM_FAULT_NORMAL);
pcb->pcb_onfault = onfault;
@ -415,6 +421,11 @@ data_abort_handler(trapframe_t *tf)
goto out;
}
if (map != kernel_map) {
PROC_LOCK(p);
p->p_lock++;
PROC_UNLOCK(p);
}
if (user == 0) {
if (pcb->pcb_onfault) {
tf->tf_r0 = error;
@ -518,8 +529,13 @@ dab_align(trapframe_t *tf, u_int fsr, u_int far, struct thread *td, struct ksig
{
/* Alignment faults are always fatal if they occur in kernel mode */
if (!TRAP_USERMODE(tf))
dab_fatal(tf, fsr, far, td, ksig);
if (!TRAP_USERMODE(tf)) {
if (!td || !td->td_pcb->pcb_onfault)
dab_fatal(tf, fsr, far, td, ksig);
tf->tf_r0 = EFAULT;
tf->tf_pc = (int)td->td_pcb->pcb_onfault;
return (0);
}
/* pcb_onfault *must* be NULL at this point */
@ -676,12 +692,14 @@ void
prefetch_abort_handler(trapframe_t *tf)
{
struct thread *td;
struct proc * p;
struct vm_map *map;
vm_offset_t fault_pc, va;
int error = 0;
u_int sticks = 0;
struct ksig ksig;
#if 0
/* Update vmmeter statistics */
uvmexp.traps++;
@ -692,11 +710,14 @@ prefetch_abort_handler(trapframe_t *tf)
#endif
td = curthread;
p = td->td_proc;
if (TRAP_USERMODE(tf)) {
td->td_frame = tf;
if (td->td_ucred != td->td_proc->p_ucred)
cred_update_thread(td);
if (td->td_proc->p_flag & P_SA)
thread_user_enter(td);
}
fault_pc = tf->tf_pc;
if (td->td_critnest == 0 &&
@ -721,8 +742,6 @@ prefetch_abort_handler(trapframe_t *tf)
/* Prefetch aborts cannot happen in kernel mode */
if (__predict_false(!TRAP_USERMODE(tf)))
dab_fatal(tf, 0, tf->tf_pc, NULL, &ksig);
/* Get fault address */
td->td_frame = tf;
sticks = td->td_sticks;
@ -746,8 +765,20 @@ prefetch_abort_handler(trapframe_t *tf)
if (pmap_fault_fixup(map->pmap, va, VM_PROT_READ, 1))
goto out;
if (map != kernel_map) {
PROC_LOCK(p);
p->p_lock++;
PROC_UNLOCK(p);
}
error = vm_fault(map, va, VM_PROT_READ | VM_PROT_EXECUTE,
VM_FAULT_NORMAL);
if (map != kernel_map) {
PROC_LOCK(p);
p->p_lock--;
PROC_UNLOCK(p);
}
if (__predict_true(error == 0))
goto out;
@ -861,16 +892,14 @@ syscall(struct thread *td, trapframe_t *frame, u_int32_t insn)
else
callp = &p->p_sysent->sv_table[code];
nargs = callp->sy_narg & SYF_ARGMASK;
if (nargs <= nap)
args = ap;
else {
memcpy(copyargs, ap, nap * sizeof(register_t));
memcpy(copyargs, ap, nap * sizeof(register_t));
if (nargs > nap) {
error = copyin((void *)frame->tf_usr_sp, copyargs + nap,
(nargs - nap) * sizeof(register_t));
if (error)
goto bad;
args = copyargs;
}
args = copyargs;
error = 0;
#ifdef KTRACE
if (KTRPOINT(td, KTR_SYSCALL))
@ -927,14 +956,10 @@ swi_handler(trapframe_t *frame)
struct thread *td = curthread;
uint32_t insn;
/*
* Enable interrupts if they were enabled before the exception.
* Since all syscalls *should* come from user mode it will always
* be safe to enable them, but check anyway.
*/
td->td_frame = frame;
if (td->td_critnest == 0 && !(frame->tf_spsr & I32_bit))
enable_interrupts(I32_bit);
if (td->td_proc->p_flag & P_SA)
thread_user_enter(td);
/*
* Make sure the program counter is correctly aligned so we
* don't take an alignment fault trying to read the opcode.
@ -945,7 +970,14 @@ swi_handler(trapframe_t *frame)
return;
}
insn = *(u_int32_t *)(frame->tf_pc - INSN_SIZE);
td->td_frame = frame;
/*
* Enable interrupts if they were enabled before the exception.
* Since all syscalls *should* come from user mode it will always
* be safe to enable them, but check anyway.
*/
if (td->td_critnest == 0 && !(frame->tf_spsr & I32_bit))
enable_interrupts(I32_bit);
syscall(td, frame, insn);
}