Newer versions of gcc don't support treating structures passed by value

as if they were really passed by reference. Specifically, the dead stores
elimination pass in the GCC 4.1 optimiser breaks the non-compliant behavior
on which FreeBSD relied. This change brings FreeBSD up to date by switching
trap frames to being explicitly passed by reference.

Reviewed by: kan
Tested by: kan
This commit is contained in:
Kip Macy 2006-12-17 06:48:40 +00:00
parent a5c5d4402c
commit e5f8d4099d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=165303
9 changed files with 82 additions and 79 deletions

View file

@ -60,6 +60,7 @@ IDTVEC(vec_name) ; \
jz 2f ; \
addl $(32 * index),%eax ; \
1: ; \
movq %rsp, %rsi ; \
movl %eax, %edi ; /* pass the IRQ */ \
call lapic_handle_intr ; \
MEXITCOUNT ; \
@ -98,7 +99,7 @@ IDTVEC(spuriousint)
IDTVEC(timerint)
PUSH_FRAME
FAKE_MCOUNT(TF_RIP(%rsp))
movq %rsp, %rdi
call lapic_handle_timer
MEXITCOUNT
jmp doreti

View file

@ -165,6 +165,7 @@ alltraps_pushregs_no_rdi:
.globl calltrap
.type calltrap,@function
calltrap:
movq %rsp, %rdi
call trap
MEXITCOUNT
jmp doreti /* Handle any pending ASTs */
@ -267,6 +268,7 @@ IDTVEC(fast_syscall)
movq %r14,TF_R14(%rsp) /* C preserved */
movq %r15,TF_R15(%rsp) /* C preserved */
FAKE_MCOUNT(TF_RIP(%rsp))
movq %rsp, %rdi
call syscall
movq PCPU(CURPCB),%rax
testq $PCB_FULLCTX,PCB_FLAGS(%rax)

View file

@ -610,18 +610,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;
@ -654,16 +654,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. */
@ -671,7 +671,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

@ -94,8 +94,8 @@ __FBSDID("$FreeBSD$");
#endif
#include <machine/tss.h>
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);
static void trap_fatal(struct trapframe *, vm_offset_t);
@ -155,8 +155,7 @@ extern char *syscallnames[];
*/
void
trap(frame)
struct trapframe frame;
trap(struct trapframe *frame)
{
struct thread *td = curthread;
struct proc *p = td->td_proc;
@ -165,7 +164,7 @@ trap(frame)
ksiginfo_t ksi;
PCPU_LAZY_INC(cnt.v_trap);
type = frame.tf_trapno;
type = frame->tf_trapno;
#ifdef SMP
#ifdef STOP_NMI
@ -192,12 +191,12 @@ trap(frame)
* the NMI was handled by it and we can return immediately.
*/
if (type == T_NMI && pmc_intr &&
(*pmc_intr)(PCPU_GET(cpuid), (uintptr_t) frame.tf_rip,
TRAPF_USERMODE(&frame)))
(*pmc_intr)(PCPU_GET(cpuid), (uintptr_t) frame->tf_rip,
TRAPF_USERMODE(frame)))
goto out;
#endif
if ((frame.tf_rflags & PSL_I) == 0) {
if ((frame->tf_rflags & PSL_I) == 0) {
/*
* Buggy application or kernel code has disabled
* interrupts and then trapped. Enabling interrupts
@ -205,7 +204,7 @@ trap(frame)
* interrupts disabled until they are accidentally
* enabled later.
*/
if (ISPL(frame.tf_cs) == SEL_UPL)
if (ISPL(frame->tf_cs) == SEL_UPL)
printf(
"pid %ld (%s): trap %d with interrupts disabled\n",
(long)curproc->p_pid, curproc->p_comm, type);
@ -226,7 +225,7 @@ trap(frame)
}
}
code = frame.tf_err;
code = frame->tf_err;
if (type == T_PAGEFLT) {
/*
* If we get a page fault while in a critical section, then
@ -245,15 +244,15 @@ trap(frame)
if (td->td_critnest != 0 ||
WITNESS_CHECK(WARN_SLEEPOK | WARN_GIANTOK, NULL,
"Kernel page fault") != 0)
trap_fatal(&frame, frame.tf_addr);
trap_fatal(frame, frame->tf_addr);
}
if (ISPL(frame.tf_cs) == SEL_UPL) {
if (ISPL(frame->tf_cs) == SEL_UPL) {
/* user trap */
td->td_pticks = 0;
td->td_frame = &frame;
addr = frame.tf_rip;
td->td_frame = frame;
addr = frame->tf_rip;
if (td->td_ucred != p->p_ucred)
cred_update_thread(td);
@ -266,7 +265,7 @@ trap(frame)
case T_BPTFLT: /* bpt instruction fault */
case T_TRCTRAP: /* trace trap */
enable_intr();
frame.tf_rflags &= ~PSL_T;
frame->tf_rflags &= ~PSL_T;
i = SIGTRAP;
ucode = (type == T_TRCTRAP ? TRAP_TRACE : TRAP_BRKPT);
break;
@ -298,12 +297,12 @@ trap(frame)
break;
case T_PAGEFLT: /* page fault */
addr = frame.tf_addr;
addr = frame->tf_addr;
#ifdef KSE
if (td->td_pflags & TDP_SA)
thread_user_enter(td);
#endif
i = trap_pfault(&frame, TRUE);
i = trap_pfault(frame, TRUE);
if (i == -1)
goto userout;
if (i == 0)
@ -334,7 +333,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;
@ -380,7 +379,7 @@ trap(frame)
("kernel trap doesn't have ucred"));
switch (type) {
case T_PAGEFLT: /* page fault */
(void) trap_pfault(&frame, FALSE);
(void) trap_pfault(frame, FALSE);
goto out;
case T_DNA:
@ -413,12 +412,12 @@ trap(frame)
* selectors and pointers when the user changes
* them.
*/
if (frame.tf_rip == (long)doreti_iret) {
frame.tf_rip = (long)doreti_iret_fault;
if (frame->tf_rip == (long)doreti_iret) {
frame->tf_rip = (long)doreti_iret_fault;
goto out;
}
if (PCPU_GET(curpcb)->pcb_onfault != NULL) {
frame.tf_rip =
frame->tf_rip =
(long)PCPU_GET(curpcb)->pcb_onfault;
goto out;
}
@ -434,8 +433,8 @@ trap(frame)
* problem here and not every time the kernel is
* entered.
*/
if (frame.tf_rflags & PSL_NT) {
frame.tf_rflags &= ~PSL_NT;
if (frame->tf_rflags & PSL_NT) {
frame->tf_rflags &= ~PSL_NT;
goto out;
}
break;
@ -470,7 +469,7 @@ trap(frame)
*/
#ifdef KDB
/* XXX Giant */
if (kdb_trap(type, 0, &frame))
if (kdb_trap(type, 0, frame))
goto out;
#endif
break;
@ -487,7 +486,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;
@ -497,7 +496,7 @@ trap(frame)
#endif /* DEV_ISA */
}
trap_fatal(&frame, 0);
trap_fatal(frame, 0);
goto out;
}
@ -517,13 +516,13 @@ trap(frame)
uprintf("fatal process exception: %s",
trap_msg[type]);
if ((type == T_PAGEFLT) || (type == T_PROTFLT))
uprintf(", fault VA = 0x%lx", frame.tf_addr);
uprintf(", fault VA = 0x%lx", frame->tf_addr);
uprintf("\n");
}
#endif
user:
userret(td, &frame);
userret(td, frame);
mtx_assert(&Giant, MA_NOTOWNED);
userout:
out:
@ -723,8 +722,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;
@ -746,7 +744,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 */
@ -757,25 +755,25 @@ syscall(frame)
reg = 0;
regcnt = 6;
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_rsp + sizeof(register_t);
code = frame.tf_rax;
orig_tf_rflags = frame.tf_rflags;
params = (caddr_t)frame->tf_rsp + sizeof(register_t);
code = frame->tf_rax;
orig_tf_rflags = frame->tf_rflags;
if (p->p_sysent->sv_prepsyscall) {
/*
* The prep code is MP aware.
*/
(*p->p_sysent->sv_prepsyscall)(&frame, (int *)args, &code, &params);
(*p->p_sysent->sv_prepsyscall)(frame, (int *)args, &code, &params);
} else {
if (code == SYS_syscall || code == SYS___syscall) {
code = frame.tf_rdi;
code = frame->tf_rdi;
reg++;
regcnt--;
}
@ -797,7 +795,7 @@ syscall(frame)
KASSERT(narg <= sizeof(args) / sizeof(args[0]),
("Too many syscall arguments!"));
error = 0;
argp = &frame.tf_rdi;
argp = &frame->tf_rdi;
argp += reg;
bcopy(argp, args, sizeof(args[0]) * regcnt);
if (narg > regcnt) {
@ -817,7 +815,7 @@ syscall(frame)
if (error == 0) {
td->td_retval[0] = 0;
td->td_retval[1] = frame.tf_rdx;
td->td_retval[1] = frame->tf_rdx;
STOPEVENT(p, S_SCE, narg);
@ -830,9 +828,9 @@ syscall(frame)
switch (error) {
case 0:
frame.tf_rax = td->td_retval[0];
frame.tf_rdx = td->td_retval[1];
frame.tf_rflags &= ~PSL_C;
frame->tf_rax = td->td_retval[0];
frame->tf_rdx = td->td_retval[1];
frame->tf_rflags &= ~PSL_C;
break;
case ERESTART:
@ -842,8 +840,8 @@ syscall(frame)
* (which was holding the value of %rcx) is restored for
* the next iteration.
*/
frame.tf_rip -= frame.tf_err;
frame.tf_r10 = frame.tf_rcx;
frame->tf_rip -= frame->tf_err;
frame->tf_r10 = frame->tf_rcx;
td->td_pcb->pcb_flags |= PCB_FULLCTX;
break;
@ -857,8 +855,8 @@ syscall(frame)
else
error = p->p_sysent->sv_errtbl[error];
}
frame.tf_rax = error;
frame.tf_rflags |= PSL_C;
frame->tf_rax = error;
frame->tf_rflags |= PSL_C;
break;
}
@ -866,11 +864,11 @@ syscall(frame)
* Traced syscall.
*/
if (orig_tf_rflags & PSL_T) {
frame.tf_rflags &= ~PSL_T;
frame->tf_rflags &= ~PSL_T;
ksiginfo_init_trap(&ksi);
ksi.ksi_signo = SIGTRAP;
ksi.ksi_code = TRAP_TRACE;
ksi.ksi_addr = (void *)frame.tf_rip;
ksi.ksi_addr = (void *)frame->tf_rip;
trapsignal(td, &ksi);
}
@ -890,7 +888,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

@ -61,6 +61,7 @@ IDTVEC(int0x80_syscall)
movq %r14,TF_R14(%rsp)
movq %r15,TF_R15(%rsp)
FAKE_MCOUNT(TF_RIP(%rsp))
movq %rsp, %rdi
call ia32_syscall
MEXITCOUNT
jmp doreti

View file

@ -86,10 +86,10 @@ __FBSDID("$FreeBSD$");
extern inthand_t IDTVEC(int0x80_syscall), IDTVEC(rsvd);
extern const char *freebsd32_syscallnames[];
void ia32_syscall(struct trapframe frame); /* Called from asm code */
void ia32_syscall(struct trapframe *frame); /* Called from asm code */
void
ia32_syscall(struct trapframe frame)
ia32_syscall(struct trapframe *frame)
{
caddr_t params;
int i;
@ -111,18 +111,18 @@ ia32_syscall(struct trapframe frame)
PCPU_LAZY_INC(cnt.v_syscall);
td->td_pticks = 0;
td->td_frame = &frame;
td->td_frame = frame;
if (td->td_ucred != p->p_ucred)
cred_update_thread(td);
params = (caddr_t)frame.tf_rsp + sizeof(u_int32_t);
code = frame.tf_rax;
orig_tf_rflags = frame.tf_rflags;
params = (caddr_t)frame->tf_rsp + sizeof(u_int32_t);
code = frame->tf_rax;
orig_tf_rflags = frame->tf_rflags;
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.
@ -177,7 +177,7 @@ ia32_syscall(struct trapframe frame)
if (error == 0) {
td->td_retval[0] = 0;
td->td_retval[1] = frame.tf_rdx;
td->td_retval[1] = frame->tf_rdx;
STOPEVENT(p, S_SCE, narg);
@ -190,9 +190,9 @@ ia32_syscall(struct trapframe frame)
switch (error) {
case 0:
frame.tf_rax = td->td_retval[0];
frame.tf_rdx = td->td_retval[1];
frame.tf_rflags &= ~PSL_C;
frame->tf_rax = td->td_retval[0];
frame->tf_rdx = td->td_retval[1];
frame->tf_rflags &= ~PSL_C;
break;
case ERESTART:
@ -200,7 +200,7 @@ ia32_syscall(struct trapframe frame)
* Reconstruct pc, assuming lcall $X,y is 7 bytes,
* int 0x80 is 2 bytes. We saved this in tf_err.
*/
frame.tf_rip -= frame.tf_err;
frame->tf_rip -= frame->tf_err;
break;
case EJUSTRETURN:
@ -213,8 +213,8 @@ ia32_syscall(struct trapframe frame)
else
error = p->p_sysent->sv_errtbl[error];
}
frame.tf_rax = error;
frame.tf_rflags |= PSL_C;
frame->tf_rax = error;
frame->tf_rflags |= PSL_C;
break;
}
@ -222,11 +222,11 @@ ia32_syscall(struct trapframe frame)
* Traced syscall.
*/
if (orig_tf_rflags & PSL_T) {
frame.tf_rflags &= ~PSL_T;
frame->tf_rflags &= ~PSL_T;
ksiginfo_init_trap(&ksi);
ksi.ksi_signo = SIGTRAP;
ksi.ksi_code = TRAP_TRACE;
ksi.ksi_addr = (void *)frame.tf_rip;
ksi.ksi_addr = (void *)frame->tf_rip;
trapsignal(td, &ksi);
}
@ -246,7 +246,7 @@ ia32_syscall(struct trapframe 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

@ -202,8 +202,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

@ -494,7 +494,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;
@ -521,7 +521,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

@ -49,6 +49,7 @@
IDTVEC(vec_name) ; \
PUSH_FRAME ; \
FAKE_MCOUNT(TF_RIP(%rsp)) ; \
movq %rsp, %rsi ; \
movl $irq_num, %edi; /* pass the IRQ */ \
call atpic_handle_intr ; \
MEXITCOUNT ; \