Evidently FreeBSD has long relied on the compiler to treat structures

passed by value (trap frames) as if they were in fact being passed by
reference. For better or worse, this incorrect behaviour is no longer
present in gcc 4.1. In this patch I convert all trapframe arguments to
be explicitly pass by reference. I also remove vm86_initflags, pushing
the very little work that it actually does up into vm86_prepcall.

Reviewed by: kan
Tested by: kan
This commit is contained in:
Kip Macy 2006-12-17 05:07:01 +00:00
parent 9c50a94180
commit a5c5d4402c
10 changed files with 105 additions and 103 deletions

View File

@ -63,9 +63,10 @@ IDTVEC(vec_name) ; \
jz 2f ; \
addl $(32 * index),%eax ; \
1: ; \
pushl %esp ; \
pushl %eax ; /* pass the IRQ */ \
call lapic_handle_intr ; \
addl $4, %esp ; /* discard parameter */ \
addl $8, %esp ; /* discard parameter */ \
MEXITCOUNT ; \
jmp doreti ; \
2: movl $-1, %eax ; /* send a vector of -1 */ \
@ -103,8 +104,9 @@ IDTVEC(timerint)
PUSH_FRAME
SET_KERNEL_SREGS
FAKE_MCOUNT(TF_EIP(%esp))
pushl %esp
call lapic_handle_timer
add $4, %esp
MEXITCOUNT
jmp doreti

View File

@ -135,8 +135,10 @@ alltraps_with_regs_pushed:
SET_KERNEL_SREGS
FAKE_MCOUNT(TF_EIP(%esp))
calltrap:
pushl %esp
call trap
add $4, %esp
/*
* Return via doreti to handle ASTs.
*/
@ -167,7 +169,9 @@ IDTVEC(lcall_syscall)
pushl %fs
SET_KERNEL_SREGS
FAKE_MCOUNT(TF_EIP(%esp))
pushl %esp
call syscall
add $4, %esp
MEXITCOUNT
jmp doreti
@ -188,7 +192,9 @@ IDTVEC(int0x80_syscall)
pushl %fs
SET_KERNEL_SREGS
FAKE_MCOUNT(TF_EIP(%esp))
pushl %esp
call syscall
add $4, %esp
MEXITCOUNT
jmp doreti

View File

@ -612,18 +612,18 @@ lapic_eoi(void)
}
void
lapic_handle_intr(int vector, struct trapframe frame)
lapic_handle_intr(int vector, struct trapframe *frame)
{
struct intsrc *isrc;
if (vector == -1)
panic("Couldn't get vector from ISR!");
isrc = intr_lookup_source(apic_idt_to_irq(vector));
intr_execute_handlers(isrc, &frame);
intr_execute_handlers(isrc, frame);
}
void
lapic_handle_timer(struct trapframe frame)
lapic_handle_timer(struct trapframe *frame)
{
struct lapic *la;
@ -656,16 +656,16 @@ lapic_handle_timer(struct trapframe frame)
if (la->la_hard_ticks >= lapic_timer_hz) {
la->la_hard_ticks -= lapic_timer_hz;
if (PCPU_GET(cpuid) == 0)
hardclock(TRAPF_USERMODE(&frame), TRAPF_PC(&frame));
hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
else
hardclock_cpu(TRAPF_USERMODE(&frame));
hardclock_cpu(TRAPF_USERMODE(frame));
}
/* Fire statclock at stathz. */
la->la_stat_ticks += stathz;
if (la->la_stat_ticks >= lapic_timer_hz) {
la->la_stat_ticks -= lapic_timer_hz;
statclock(TRAPF_USERMODE(&frame));
statclock(TRAPF_USERMODE(frame));
}
/* Fire profclock at profhz, but only when needed. */
@ -673,7 +673,7 @@ lapic_handle_timer(struct trapframe frame)
if (la->la_prof_ticks >= lapic_timer_hz) {
la->la_prof_ticks -= lapic_timer_hz;
if (profprocs != 0)
profclock(TRAPF_USERMODE(&frame), TRAPF_PC(&frame));
profclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
}
critical_exit();
}

View File

@ -102,8 +102,8 @@ __FBSDID("$FreeBSD$");
#include <machine/clock.h>
#endif
extern void trap(struct trapframe frame);
extern void syscall(struct trapframe frame);
extern void trap(struct trapframe *frame);
extern void syscall(struct trapframe *frame);
static int trap_pfault(struct trapframe *, int, vm_offset_t);
static void trap_fatal(struct trapframe *, vm_offset_t);
@ -169,8 +169,7 @@ extern char *syscallnames[];
*/
void
trap(frame)
struct trapframe frame;
trap(struct trapframe *frame)
{
struct thread *td = curthread;
struct proc *p = td->td_proc;
@ -183,7 +182,7 @@ trap(frame)
#endif
PCPU_LAZY_INC(cnt.v_trap);
type = frame.tf_trapno;
type = frame->tf_trapno;
#ifdef SMP
#ifdef STOP_NMI
@ -211,12 +210,12 @@ trap(frame)
* return immediately.
*/
if (type == T_NMI && pmc_intr &&
(*pmc_intr)(PCPU_GET(cpuid), (uintptr_t) frame.tf_eip,
TRAPF_USERMODE(&frame)))
(*pmc_intr)(PCPU_GET(cpuid), (uintptr_t) frame->tf_eip,
TRAPF_USERMODE(frame)))
goto out;
#endif
if ((frame.tf_eflags & PSL_I) == 0) {
if ((frame->tf_eflags & PSL_I) == 0) {
/*
* Buggy application or kernel code has disabled
* interrupts and then trapped. Enabling interrupts
@ -224,12 +223,12 @@ trap(frame)
* interrupts disabled until they are accidentally
* enabled later.
*/
if (ISPL(frame.tf_cs) == SEL_UPL || (frame.tf_eflags & PSL_VM))
if (ISPL(frame->tf_cs) == SEL_UPL || (frame->tf_eflags & PSL_VM))
printf(
"pid %ld (%s): trap %d with interrupts disabled\n",
(long)curproc->p_pid, curproc->p_comm, type);
else if (type != T_BPTFLT && type != T_TRCTRAP &&
frame.tf_eip != (int)cpu_switch_load_gs) {
frame->tf_eip != (int)cpu_switch_load_gs) {
/*
* XXX not quite right, since this may be for a
* multiple fault in user mode.
@ -248,7 +247,7 @@ trap(frame)
}
eva = 0;
code = frame.tf_err;
code = frame->tf_err;
if (type == T_PAGEFLT) {
/*
* For some Cyrix CPUs, %cr2 is clobbered by
@ -274,19 +273,19 @@ trap(frame)
if (td->td_critnest != 0 ||
WITNESS_CHECK(WARN_SLEEPOK | WARN_GIANTOK, NULL,
"Kernel page fault") != 0)
trap_fatal(&frame, eva);
trap_fatal(frame, eva);
else
enable_intr();
}
if ((ISPL(frame.tf_cs) == SEL_UPL) ||
((frame.tf_eflags & PSL_VM) &&
if ((ISPL(frame->tf_cs) == SEL_UPL) ||
((frame->tf_eflags & PSL_VM) &&
!(PCPU_GET(curpcb)->pcb_flags & PCB_VM86CALL))) {
/* user trap */
td->td_pticks = 0;
td->td_frame = &frame;
addr = frame.tf_eip;
td->td_frame = frame;
addr = frame->tf_eip;
if (td->td_ucred != p->p_ucred)
cred_update_thread(td);
@ -299,7 +298,7 @@ trap(frame)
case T_BPTFLT: /* bpt instruction fault */
case T_TRCTRAP: /* trace trap */
enable_intr();
frame.tf_eflags &= ~PSL_T;
frame->tf_eflags &= ~PSL_T;
i = SIGTRAP;
ucode = (type == T_TRCTRAP ? TRAP_TRACE : TRAP_BRKPT);
break;
@ -322,8 +321,8 @@ trap(frame)
*/
case T_PROTFLT: /* general protection fault */
case T_STKFLT: /* stack fault */
if (frame.tf_eflags & PSL_VM) {
i = vm86_emulate((struct vm86frame *)&frame);
if (frame->tf_eflags & PSL_VM) {
i = vm86_emulate((struct vm86frame *)frame);
if (i == 0)
goto user;
break;
@ -351,7 +350,7 @@ trap(frame)
thread_user_enter(td);
#endif
i = trap_pfault(&frame, TRUE, eva);
i = trap_pfault(frame, TRUE, eva);
#if defined(I586_CPU) && !defined(NO_F00F_HACK)
if (i == -2) {
/*
@ -359,7 +358,7 @@ trap(frame)
* treat the fault as an illegal instruction
* (T_PRIVINFLT) instead of a page fault.
*/
type = frame.tf_trapno = T_PRIVINFLT;
type = frame->tf_trapno = T_PRIVINFLT;
/* Proceed as in that case. */
ucode = ILL_PRVOPC;
@ -411,7 +410,7 @@ trap(frame)
*/
if (kdb_on_nmi) {
printf ("NMI ... going to debugger\n");
kdb_trap(type, 0, &frame);
kdb_trap(type, 0, frame);
}
#endif /* KDB */
goto userout;
@ -460,7 +459,7 @@ trap(frame)
("kernel trap doesn't have ucred"));
switch (type) {
case T_PAGEFLT: /* page fault */
(void) trap_pfault(&frame, FALSE, eva);
(void) trap_pfault(frame, FALSE, eva);
goto out;
case T_DNA:
@ -482,13 +481,13 @@ trap(frame)
*/
case T_PROTFLT: /* general protection fault */
case T_STKFLT: /* stack fault */
if (frame.tf_eflags & PSL_VM) {
i = vm86_emulate((struct vm86frame *)&frame);
if (frame->tf_eflags & PSL_VM) {
i = vm86_emulate((struct vm86frame *)frame);
if (i != 0)
/*
* returns to original process
*/
vm86_trap((struct vm86frame *)&frame);
vm86_trap((struct vm86frame *)frame);
goto out;
}
if (type == T_STKFLT)
@ -509,7 +508,7 @@ trap(frame)
* (XXX) so that we can continue, and generate
* a signal.
*/
if (frame.tf_eip == (int)cpu_switch_load_gs) {
if (frame->tf_eip == (int)cpu_switch_load_gs) {
PCPU_GET(curpcb)->pcb_gs = 0;
#if 0
PROC_LOCK(p);
@ -532,24 +531,24 @@ trap(frame)
* selectors and pointers when the user changes
* them.
*/
if (frame.tf_eip == (int)doreti_iret) {
frame.tf_eip = (int)doreti_iret_fault;
if (frame->tf_eip == (int)doreti_iret) {
frame->tf_eip = (int)doreti_iret_fault;
goto out;
}
if (frame.tf_eip == (int)doreti_popl_ds) {
frame.tf_eip = (int)doreti_popl_ds_fault;
if (frame->tf_eip == (int)doreti_popl_ds) {
frame->tf_eip = (int)doreti_popl_ds_fault;
goto out;
}
if (frame.tf_eip == (int)doreti_popl_es) {
frame.tf_eip = (int)doreti_popl_es_fault;
if (frame->tf_eip == (int)doreti_popl_es) {
frame->tf_eip = (int)doreti_popl_es_fault;
goto out;
}
if (frame.tf_eip == (int)doreti_popl_fs) {
frame.tf_eip = (int)doreti_popl_fs_fault;
if (frame->tf_eip == (int)doreti_popl_fs) {
frame->tf_eip = (int)doreti_popl_fs_fault;
goto out;
}
if (PCPU_GET(curpcb)->pcb_onfault != NULL) {
frame.tf_eip =
frame->tf_eip =
(int)PCPU_GET(curpcb)->pcb_onfault;
goto out;
}
@ -565,14 +564,14 @@ trap(frame)
* problem here and not every time the kernel is
* entered.
*/
if (frame.tf_eflags & PSL_NT) {
frame.tf_eflags &= ~PSL_NT;
if (frame->tf_eflags & PSL_NT) {
frame->tf_eflags &= ~PSL_NT;
goto out;
}
break;
case T_TRCTRAP: /* trace trap */
if (frame.tf_eip == (int)IDTVEC(lcall_syscall)) {
if (frame->tf_eip == (int)IDTVEC(lcall_syscall)) {
/*
* We've just entered system mode via the
* syscall lcall. Continue single stepping
@ -581,12 +580,12 @@ trap(frame)
*/
goto out;
}
if (frame.tf_eip == (int)IDTVEC(lcall_syscall) + 1) {
if (frame->tf_eip == (int)IDTVEC(lcall_syscall) + 1) {
/*
* The syscall handler has now saved the
* flags. Stop single stepping it.
*/
frame.tf_eflags &= ~PSL_T;
frame->tf_eflags &= ~PSL_T;
goto out;
}
/*
@ -619,7 +618,7 @@ trap(frame)
*/
#ifdef KDB
/* XXX Giant */
if (kdb_trap(type, 0, &frame))
if (kdb_trap(type, 0, frame))
goto out;
#endif
break;
@ -646,7 +645,7 @@ trap(frame)
*/
if (kdb_on_nmi) {
printf ("NMI ... going to debugger\n");
kdb_trap(type, 0, &frame);
kdb_trap(type, 0, frame);
}
#endif /* KDB */
goto out;
@ -657,7 +656,7 @@ trap(frame)
#endif /* DEV_ISA */
}
trap_fatal(&frame, eva);
trap_fatal(frame, eva);
goto out;
}
@ -683,7 +682,7 @@ trap(frame)
#endif
user:
userret(td, &frame);
userret(td, frame);
mtx_assert(&Giant, MA_NOTOWNED);
userout:
out:
@ -904,8 +903,7 @@ dblfault_handler()
* A system call is essentially treated as a trap.
*/
void
syscall(frame)
struct trapframe frame;
syscall(struct trapframe *frame)
{
caddr_t params;
struct sysent *callp;
@ -925,7 +923,7 @@ syscall(frame)
PCPU_LAZY_INC(cnt.v_syscall);
#ifdef DIAGNOSTIC
if (ISPL(frame.tf_cs) != SEL_UPL) {
if (ISPL(frame->tf_cs) != SEL_UPL) {
mtx_lock(&Giant); /* try to stabilize the system XXX */
panic("syscall");
/* NOT REACHED */
@ -934,22 +932,22 @@ syscall(frame)
#endif
td->td_pticks = 0;
td->td_frame = &frame;
td->td_frame = frame;
if (td->td_ucred != p->p_ucred)
cred_update_thread(td);
#ifdef KSE
if (p->p_flag & P_SA)
thread_user_enter(td);
#endif
params = (caddr_t)frame.tf_esp + sizeof(int);
code = frame.tf_eax;
orig_tf_eflags = frame.tf_eflags;
params = (caddr_t)frame->tf_esp + sizeof(int);
code = frame->tf_eax;
orig_tf_eflags = frame->tf_eflags;
if (p->p_sysent->sv_prepsyscall) {
/*
* The prep code is MP aware.
*/
(*p->p_sysent->sv_prepsyscall)(&frame, args, &code, &params);
(*p->p_sysent->sv_prepsyscall)(frame, args, &code, &params);
} else {
/*
* Need to check if this is a 32 bit or 64 bit syscall.
@ -1000,7 +998,7 @@ syscall(frame)
if (error == 0) {
td->td_retval[0] = 0;
td->td_retval[1] = frame.tf_edx;
td->td_retval[1] = frame->tf_edx;
STOPEVENT(p, S_SCE, narg);
@ -1013,9 +1011,9 @@ syscall(frame)
switch (error) {
case 0:
frame.tf_eax = td->td_retval[0];
frame.tf_edx = td->td_retval[1];
frame.tf_eflags &= ~PSL_C;
frame->tf_eax = td->td_retval[0];
frame->tf_edx = td->td_retval[1];
frame->tf_eflags &= ~PSL_C;
break;
case ERESTART:
@ -1023,7 +1021,7 @@ syscall(frame)
* Reconstruct pc, assuming lcall $X,y is 7 bytes,
* int 0x80 is 2 bytes. We saved this in tf_err.
*/
frame.tf_eip -= frame.tf_err;
frame->tf_eip -= frame->tf_err;
break;
case EJUSTRETURN:
@ -1036,8 +1034,8 @@ syscall(frame)
else
error = p->p_sysent->sv_errtbl[error];
}
frame.tf_eax = error;
frame.tf_eflags |= PSL_C;
frame->tf_eax = error;
frame->tf_eflags |= PSL_C;
break;
}
@ -1045,11 +1043,11 @@ syscall(frame)
* Traced syscall.
*/
if ((orig_tf_eflags & PSL_T) && !(orig_tf_eflags & PSL_VM)) {
frame.tf_eflags &= ~PSL_T;
frame->tf_eflags &= ~PSL_T;
ksiginfo_init_trap(&ksi);
ksi.ksi_signo = SIGTRAP;
ksi.ksi_code = TRAP_TRACE;
ksi.ksi_addr = (void *)frame.tf_eip;
ksi.ksi_addr = (void *)frame->tf_eip;
trapsignal(td, &ksi);
}
@ -1069,7 +1067,7 @@ syscall(frame)
/*
* Handle reschedule and other end-of-syscall issues
*/
userret(td, &frame);
userret(td, frame);
CTR4(KTR_SYSC, "syscall exit thread %p pid %d proc %s code %d", td,
td->td_proc->p_pid, td->td_proc->p_comm, code);

View File

@ -55,7 +55,7 @@ static struct mtx vm86_lock;
extern int vm86_bioscall(struct vm86frame *);
extern void vm86_biosret(struct vm86frame *);
void vm86_prepcall(struct vm86frame);
void vm86_prepcall(struct vm86frame *);
struct system_map {
int type;
@ -506,40 +506,33 @@ vm86_addpage(struct vm86context *vmc, int pagenum, vm_offset_t kva)
panic("vm86_addpage: not enough room");
}
static void
vm86_initflags(struct vm86frame *vmf)
{
struct vm86_kernel *vm86 = &PCPU_GET(curpcb)->pcb_ext->ext_vm86;
if (!vm86->vm86_has_vme)
vm86->vm86_eflags = vmf->vmf_eflags; /* save VIF, VIP */
vmf->vmf_eflags |= PSL_VM;
}
/*
* called from vm86_bioscall, while in vm86 address space, to finalize setup.
*/
void
vm86_prepcall(struct vm86frame vmf)
vm86_prepcall(struct vm86frame *vmf)
{
uintptr_t addr[] = { 0xA00, 0x1000 }; /* code, stack */
u_char intcall[] = {
CLI, INTn, 0x00, STI, HLT
};
struct vm86_kernel *vm86;
if ((vmf.vmf_trapno & PAGE_MASK) <= 0xff) {
if ((vmf->vmf_trapno & PAGE_MASK) <= 0xff) {
/* interrupt call requested */
intcall[2] = (u_char)(vmf.vmf_trapno & 0xff);
intcall[2] = (u_char)(vmf->vmf_trapno & 0xff);
memcpy((void *)addr[0], (void *)intcall, sizeof(intcall));
vmf.vmf_ip = addr[0];
vmf.vmf_cs = 0;
vmf->vmf_ip = addr[0];
vmf->vmf_cs = 0;
}
vmf.vmf_sp = addr[1] - 2; /* keep aligned */
vmf.kernel_fs = vmf.kernel_es = vmf.kernel_ds = 0;
vmf.vmf_ss = 0;
vmf.vmf_eflags = PSL_VIF | PSL_VM | PSL_USER;
vm86_initflags(&vmf);
vmf->vmf_sp = addr[1] - 2; /* keep aligned */
vmf->kernel_fs = vmf->kernel_es = vmf->kernel_ds = 0;
vmf->vmf_ss = 0;
vmf->vmf_eflags = PSL_VIF | PSL_VM | PSL_USER;
vm86 = &PCPU_GET(curpcb)->pcb_ext->ext_vm86;
if (!vm86->vm86_has_vme)
vm86->vm86_eflags = vmf->vmf_eflags; /* save VIF, VIP */
}
/*

View File

@ -128,9 +128,11 @@ ENTRY(vm86_bioscall)
#endif
movl %ecx,%cr3 /* new page tables */
movl SCR_VMFRAME(%edx),%esp /* switch to new stack */
call vm86_prepcall /* finish setup */
pushl %esp
call vm86_prepcall /* finish setup */
add $4, %esp
/*
* Return via doreti
*/

View File

@ -201,8 +201,8 @@ int lapic_intr_pending(u_int vector);
void lapic_ipi_raw(register_t icrlo, u_int dest);
void lapic_ipi_vectored(u_int vector, int dest);
int lapic_ipi_wait(int delay);
void lapic_handle_intr(int vector, struct trapframe frame);
void lapic_handle_timer(struct trapframe frame);
void lapic_handle_intr(int vector, struct trapframe *frame);
void lapic_handle_timer(struct trapframe *frame);
void lapic_set_logical_id(u_int apic_id, u_int cluster, u_int cluster_id);
int lapic_set_lvt_mask(u_int apic_id, u_int lvt, u_char masked);
int lapic_set_lvt_mode(u_int apic_id, u_int lvt, u_int32_t mode);

View File

@ -558,7 +558,7 @@ atpic_init(void *dummy __unused)
SYSINIT(atpic_init, SI_SUB_INTR, SI_ORDER_SECOND + 1, atpic_init, NULL)
void
atpic_handle_intr(u_int vector, struct trapframe frame)
atpic_handle_intr(u_int vector, struct trapframe *frame)
{
struct intsrc *isrc;
@ -585,7 +585,7 @@ atpic_handle_intr(u_int vector, struct trapframe frame)
if ((isr & IRQ_MASK(7)) == 0)
return;
}
intr_execute_handlers(isrc, &frame);
intr_execute_handlers(isrc, frame);
}
#ifdef DEV_ISA

View File

@ -51,9 +51,10 @@ IDTVEC(vec_name) ; \
SET_KERNEL_SREGS ; \
; \
FAKE_MCOUNT(TF_EIP(%esp)) ; \
pushl %esp ; \
pushl $irq_num; /* pass the IRQ */ \
call atpic_handle_intr ; \
addl $4, %esp ; /* discard the parameter */ \
addl $8, %esp ; /* discard the parameters */ \
; \
MEXITCOUNT ; \
jmp doreti

View File

@ -47,7 +47,7 @@
#define ICU_IMR_OFFSET 1
#endif
void atpic_handle_intr(u_int vector, struct trapframe frame);
void atpic_handle_intr(u_int vector, struct trapframe *frame);
void atpic_startup(void);
#endif /* !_I386_ISA_ICU_H_ */