- Move the code to deal with handling an IPI_STOP IPI out of

ipi_nmi_handler() and into a new cpustop_handler() function.  Change
  the Xcpustop IPI_STOP handler to call this function instead of
  duplicating all the same logic in assembly.
- EOI the local APIC for the lapic timer interrupt in C rather than
  assembly.
- Bump the lazypmap IPI counter if COUNT_IPIS is defined in C rather than
  assembly.
This commit is contained in:
John Baldwin 2005-12-05 22:25:41 +00:00
parent 7e70788a5c
commit f0b9813920
5 changed files with 34 additions and 49 deletions

View File

@ -102,10 +102,6 @@ IDTVEC(spuriousint)
IDTVEC(timerint)
PUSH_FRAME
SET_KERNEL_SREGS
movl lapic, %edx
movl $0, LA_EOI(%edx) /* End Of Interrupt to APIC */
FAKE_MCOUNT(TF_EIP(%esp))
pushl $0 /* XXX convert trapframe to clockframe */
@ -260,11 +256,7 @@ IDTVEC(ipi_intr_bitmap_handler)
jmp doreti
/*
* Executed by a CPU when it receives an Xcpustop IPI from another CPU,
*
* - Signals its receipt.
* - Waits for permission to restart.
* - Signals its restart.
* Executed by a CPU when it receives an IPI_STOP from another CPU.
*/
.text
SUPERALIGN_TEXT
@ -275,36 +267,8 @@ IDTVEC(cpustop)
movl lapic, %eax
movl $0, LA_EOI(%eax) /* End Of Interrupt to APIC */
movl PCPU(CPUID), %eax
imull $PCB_SIZE, %eax
leal CNAME(stoppcbs)(%eax), %eax
pushl %eax
call CNAME(savectx) /* Save process context */
addl $4, %esp
call cpustop_handler
movl PCPU(CPUID), %eax
lock
btsl %eax, CNAME(stopped_cpus) /* stopped_cpus |= (1<<id) */
1:
btl %eax, CNAME(started_cpus) /* while (!(started_cpus & (1<<id))) */
jnc 1b
lock
btrl %eax, CNAME(started_cpus) /* started_cpus &= ~(1<<id) */
lock
btrl %eax, CNAME(stopped_cpus) /* stopped_cpus &= ~(1<<id) */
test %eax, %eax
jnz 2f
movl CNAME(cpustop_restartfunc), %eax
test %eax, %eax
jz 2f
movl $0, CNAME(cpustop_restartfunc) /* One-shot */
call *%eax
2:
POP_FRAME
iret
@ -340,11 +304,6 @@ IDTVEC(lazypmap)
PUSH_FRAME
SET_KERNEL_SREGS
#ifdef COUNT_IPIS
movl PCPU(CPUID), %eax
movl ipi_lazypmap_counts(,%eax,4), %eax
incl (%eax)
#endif
call pmap_lazyfix_action
movl lapic, %eax

View File

@ -623,6 +623,10 @@ lapic_handle_timer(struct clockframe frame)
{
struct lapic *la;
/* Send EOI first thing. */
lapic_eoi();
/* Look up our local APIC structure for the tick counters. */
la = &lapics[PCPU_GET(apic_id)];
(*la->la_timer_count)++;
critical_enter();

View File

@ -1276,15 +1276,29 @@ ipi_nmi_selected(u_int32_t cpus)
}
int
ipi_nmi_handler()
ipi_nmi_handler(void)
{
int cpu = PCPU_GET(cpuid);
int cpumask = PCPU_GET(cpumask);
if (!(ipi_nmi_pending & cpumask))
return 1;
atomic_clear_int(&ipi_nmi_pending, cpumask);
cpustop_handler();
return 0;
}
#endif /* STOP_NMI */
/*
* Handle an IPI_STOP by saving our current context and spinning until we
* are resumed.
*/
void
cpustop_handler(void)
{
int cpu = PCPU_GET(cpuid);
int cpumask = PCPU_GET(cpumask);
savectx(&stoppcbs[cpu]);
@ -1302,12 +1316,8 @@ ipi_nmi_handler()
cpustop_restartfunc();
cpustop_restartfunc = NULL;
}
return 0;
}
#endif /* STOP_NMI */
/*
* This is called once the rest of the system is up and running and we're
* ready to let the AP's out of the pen.

View File

@ -106,6 +106,7 @@ __FBSDID("$FreeBSD$");
#include "opt_cpu.h"
#include "opt_pmap.h"
#include "opt_msgbuf.h"
#include "opt_smp.h"
#include "opt_xbox.h"
#include <sys/param.h>
@ -1224,6 +1225,9 @@ pmap_lazyfix_action(void)
{
u_int mymask = PCPU_GET(cpumask);
#ifdef COUNT_IPIS
*ipi_lazypmap_counts[PCPU_GET(cpuid)]++;
#endif
if (rcr3() == lazyptd)
load_cr3(PCPU_GET(curpcb)->pcb_cr3);
atomic_clear_int(lazymask, mymask);

View File

@ -35,6 +35,13 @@ extern int mp_naps;
extern int boot_cpu_id;
extern struct pcb stoppcbs[];
extern struct mtx smp_tlb_mtx;
#ifdef COUNT_IPIS
extern u_long *ipi_invltlb_counts[MAXCPU];
extern u_long *ipi_invlrng_counts[MAXCPU];
extern u_long *ipi_invlpg_counts[MAXCPU];
extern u_long *ipi_rendezvous_counts[MAXCPU];
extern u_long *ipi_lazypmap_counts[MAXCPU];
#endif
/* IPI handlers */
inthand_t
@ -48,6 +55,7 @@ inthand_t
/* functions in mp_machdep.c */
void cpu_add(u_int apic_id, char boot_cpu);
void cpustop_handler(void);
void init_secondary(void);
void ipi_selected(u_int cpus, u_int ipi);
void ipi_all(u_int ipi);