commit 62b4b3d8eff004af575f52f3e445682ce042ddf5 Author: Mark Johnston Date: Fri Jul 24 17:35:39 2015 -0700 smp_rendezvous: provide a trap frame to rendezvous handlers On architectures where IPI handlers are invoked as interrupt filters, the trap frame is already available since the generic interrupt handler sets td_intr_frame before calling the filter. On i386 and amd64, smp_rendezvous_action() is called directly from the interrupt handler; a pointer to the trap frame can be passed as an argument. On sparc64, the trap frame is already passed as an argument, so no changes are necessary. diff --git a/sys/amd64/amd64/apic_vector.S b/sys/amd64/amd64/apic_vector.S index a1279e6..df8251d 100644 --- a/sys/amd64/amd64/apic_vector.S +++ b/sys/amd64/amd64/apic_vector.S @@ -310,6 +310,7 @@ IDTVEC(rendezvous) movq ipi_rendezvous_counts(,%rax,8), %rax incq (%rax) #endif + movq %rsp, %rdi call smp_rendezvous_action call as_lapic_eoi jmp doreti diff --git a/sys/arm/arm/mp_machdep.c b/sys/arm/arm/mp_machdep.c index 083e62e..7698201 100644 --- a/sys/arm/arm/mp_machdep.c +++ b/sys/arm/arm/mp_machdep.c @@ -258,7 +258,7 @@ ipi_handler(void *arg) switch (ipi) { case IPI_RENDEZVOUS: CTR0(KTR_SMP, "IPI_RENDEZVOUS"); - smp_rendezvous_action(); + smp_rendezvous_action(NULL); break; case IPI_AST: diff --git a/sys/arm64/arm64/mp_machdep.c b/sys/arm64/arm64/mp_machdep.c index 469627e..e81596e 100644 --- a/sys/arm64/arm64/mp_machdep.c +++ b/sys/arm64/arm64/mp_machdep.c @@ -293,7 +293,7 @@ ipi_handler(void *arg) break; case IPI_RENDEZVOUS: CTR0(KTR_SMP, "IPI_RENDEZVOUS"); - smp_rendezvous_action(); + smp_rendezvous_action(NULL); break; case IPI_STOP: case IPI_STOP_HARD: diff --git a/sys/i386/i386/apic_vector.s b/sys/i386/i386/apic_vector.s index 18b3c5d..f8edcd2 100644 --- a/sys/i386/i386/apic_vector.s +++ b/sys/i386/i386/apic_vector.s @@ -330,6 +330,7 @@ IDTVEC(rendezvous) movl ipi_rendezvous_counts(,%eax,4), %eax incl (%eax) #endif + pushl %esp call smp_rendezvous_action call as_lapic_eoi diff --git a/sys/kern/subr_smp.c b/sys/kern/subr_smp.c index 0ac3b17..7eb5b1a 100644 --- a/sys/kern/subr_smp.c +++ b/sys/kern/subr_smp.c @@ -370,9 +370,10 @@ resume_cpus(cpuset_t map) * that they are running in parallel and in an unknown lock context. */ void -smp_rendezvous_action(void) +smp_rendezvous_action(struct trapframe *frame) { struct thread *td; + struct trapframe *oldframe; void *local_func_arg; void (*local_setup_func)(void*); void (*local_action_func)(void*); @@ -381,6 +382,10 @@ smp_rendezvous_action(void) int owepreempt; #endif + td = curthread; + KASSERT(frame != NULL || td->td_intr_frame != NULL || + mtx_owned(&smp_ipi_mtx), ("no interrupt frame available")); + /* Ensure we have up-to-date values. */ atomic_add_acq_int(&smp_rv_waiters[0], 1); while (smp_rv_waiters[0] < smp_rv_ncpus) @@ -414,12 +419,16 @@ smp_rendezvous_action(void) * and thus td_owepreempt should never transition from 0 to 1 * during this routine. */ - td = curthread; td->td_critnest++; #ifdef INVARIANTS owepreempt = td->td_owepreempt; #endif - + + if (frame != NULL) { + oldframe = td->td_intr_frame; + td->td_intr_frame = frame; + } + /* * If requested, run a setup function before the main action * function. Ensure all CPUs have completed the setup @@ -463,6 +472,9 @@ smp_rendezvous_action(void) */ atomic_add_rel_int(&smp_rv_waiters[3], 1); + if (frame != NULL) + td->td_intr_frame = oldframe; + td->td_critnest--; KASSERT(owepreempt == td->td_owepreempt, ("rendezvous action changed td_owepreempt")); @@ -520,7 +532,7 @@ smp_rendezvous_cpus(cpuset_t map, /* Check if the current CPU is in the map */ if (curcpumap != 0) - smp_rendezvous_action(); + smp_rendezvous_action(NULL); /* * Ensure that the master CPU waits for all the other diff --git a/sys/mips/mips/mp_machdep.c b/sys/mips/mips/mp_machdep.c index 9f98909..a28b56b 100644 --- a/sys/mips/mips/mp_machdep.c +++ b/sys/mips/mips/mp_machdep.c @@ -133,7 +133,7 @@ mips_ipi_handler(void *arg) switch (ipi) { case IPI_RENDEZVOUS: CTR0(KTR_SMP, "IPI_RENDEZVOUS"); - smp_rendezvous_action(); + smp_rendezvous_action(NULL); break; case IPI_AST: diff --git a/sys/powerpc/powerpc/mp_machdep.c b/sys/powerpc/powerpc/mp_machdep.c index 9d26e95..53a04ae 100644 --- a/sys/powerpc/powerpc/mp_machdep.c +++ b/sys/powerpc/powerpc/mp_machdep.c @@ -298,7 +298,7 @@ powerpc_ipi_handler(void *arg) break; case IPI_RENDEZVOUS: CTR1(KTR_SMP, "%s: IPI_RENDEZVOUS", __func__); - smp_rendezvous_action(); + smp_rendezvous_action(NULL); break; case IPI_STOP: diff --git a/sys/sparc64/sparc64/mp_machdep.c b/sys/sparc64/sparc64/mp_machdep.c index c2c4e3e..e19362c 100644 --- a/sys/sparc64/sparc64/mp_machdep.c +++ b/sys/sparc64/sparc64/mp_machdep.c @@ -282,8 +282,7 @@ cpu_mp_start(void) } intr_setup(PIL_AST, cpu_ipi_ast, -1, NULL, NULL); - intr_setup(PIL_RENDEZVOUS, (ih_func_t *)smp_rendezvous_action, - -1, NULL, NULL); + intr_setup(PIL_RENDEZVOUS, smp_rendezvous_action, -1, NULL, NULL); intr_setup(PIL_STOP, cpu_ipi_stop, -1, NULL, NULL); intr_setup(PIL_PREEMPT, cpu_ipi_preempt, -1, NULL, NULL); intr_setup(PIL_HARDCLOCK, cpu_ipi_hardclock, -1, NULL, NULL); diff --git a/sys/sys/smp.h b/sys/sys/smp.h index 58b1754..1751804 100644 --- a/sys/sys/smp.h +++ b/sys/sys/smp.h @@ -153,6 +153,7 @@ cpu_next(int i) * the exact maximum ID that early, then it may set mp_maxid to MAXCPU - 1. */ struct thread; +struct trapframe; struct cpu_group *cpu_topo(void); void cpu_mp_announce(void); @@ -169,7 +170,7 @@ int suspend_cpus(cpuset_t); int resume_cpus(cpuset_t); #endif -void smp_rendezvous_action(void); +void smp_rendezvous_action(struct trapframe *); extern struct mtx smp_ipi_mtx; #endif /* SMP */ diff --git a/sys/x86/xen/xen_apic.c b/sys/x86/xen/xen_apic.c index a65f3b5..92eb6ec 100644 --- a/sys/x86/xen/xen_apic.c +++ b/sys/x86/xen/xen_apic.c @@ -409,7 +409,7 @@ xen_smp_rendezvous_action(void *arg) (*ipi_rendezvous_counts[PCPU_GET(cpuid)])++; #endif /* COUNT_IPIS */ - smp_rendezvous_action(); + smp_rendezvous_action(NULL); return (FILTER_HANDLED); }