From 20611107850a6c1de42880a35271d3a18a4b8811 Mon Sep 17 00:00:00 2001 From: kmacy Date: Sun, 17 Dec 2006 06:48:40 +0000 Subject: 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 --- sys/amd64/amd64/apic_vector.S | 3 +- sys/amd64/amd64/exception.S | 2 + sys/amd64/amd64/local_apic.c | 14 +++--- sys/amd64/amd64/trap.c | 98 ++++++++++++++++++++--------------------- sys/amd64/ia32/ia32_exception.S | 1 + sys/amd64/ia32/ia32_syscall.c | 34 +++++++------- sys/amd64/include/apicvar.h | 4 +- sys/amd64/isa/atpic.c | 4 +- sys/amd64/isa/atpic_vector.S | 1 + 9 files changed, 82 insertions(+), 79 deletions(-) (limited to 'sys/amd64') diff --git a/sys/amd64/amd64/apic_vector.S b/sys/amd64/amd64/apic_vector.S index ab781ca..14a6f87 100644 --- a/sys/amd64/amd64/apic_vector.S +++ b/sys/amd64/amd64/apic_vector.S @@ -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 diff --git a/sys/amd64/amd64/exception.S b/sys/amd64/amd64/exception.S index 9b87cee..773239f 100644 --- a/sys/amd64/amd64/exception.S +++ b/sys/amd64/amd64/exception.S @@ -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) diff --git a/sys/amd64/amd64/local_apic.c b/sys/amd64/amd64/local_apic.c index 14ce4ce..66c0d0e 100644 --- a/sys/amd64/amd64/local_apic.c +++ b/sys/amd64/amd64/local_apic.c @@ -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(); } diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c index a1772fa..7957c34 100644 --- a/sys/amd64/amd64/trap.c +++ b/sys/amd64/amd64/trap.c @@ -94,8 +94,8 @@ __FBSDID("$FreeBSD$"); #endif #include -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, ¶ms); + (*p->p_sysent->sv_prepsyscall)(frame, (int *)args, &code, ¶ms); } 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); diff --git a/sys/amd64/ia32/ia32_exception.S b/sys/amd64/ia32/ia32_exception.S index c65634e..4820f53 100644 --- a/sys/amd64/ia32/ia32_exception.S +++ b/sys/amd64/ia32/ia32_exception.S @@ -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 diff --git a/sys/amd64/ia32/ia32_syscall.c b/sys/amd64/ia32/ia32_syscall.c index e007b3a..c51a2be 100644 --- a/sys/amd64/ia32/ia32_syscall.c +++ b/sys/amd64/ia32/ia32_syscall.c @@ -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, ¶ms); + (*p->p_sysent->sv_prepsyscall)(frame, args, &code, ¶ms); } 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); diff --git a/sys/amd64/include/apicvar.h b/sys/amd64/include/apicvar.h index 6cc37c6..bd0386b 100644 --- a/sys/amd64/include/apicvar.h +++ b/sys/amd64/include/apicvar.h @@ -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); diff --git a/sys/amd64/isa/atpic.c b/sys/amd64/isa/atpic.c index 1115c92..3a88eda 100644 --- a/sys/amd64/isa/atpic.c +++ b/sys/amd64/isa/atpic.c @@ -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 diff --git a/sys/amd64/isa/atpic_vector.S b/sys/amd64/isa/atpic_vector.S index 8cddf43..e7dcbc3 100644 --- a/sys/amd64/isa/atpic_vector.S +++ b/sys/amd64/isa/atpic_vector.S @@ -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 ; \ -- cgit v1.1