Date: Wed, 25 Jun 1997 20:32:35 -0600 From: Steve Passe <smp@csn.net> To: Christopher Ulbright <ulbright@cs.washington.edu> Cc: freebsd-smp@FreeBSD.ORG Subject: Re: Debugger Message-ID: <199706260232.UAA17883@Ilsa.StevesCafe.com> In-Reply-To: Your message of "Wed, 25 Jun 1997 09:50:19 PDT." <Pine.OSF.3.96.970625094314.9321B-100000@sanjuan.cs.washington.edu>
next in thread | previous in thread | raw e-mail | index | archive | help
Hi, some suggested pseudo-code follows. please comment. ------------------------------------- cut ------------------------------------- --- /* * example usage: */ breakpoint() { ... stop_other_cpus(cpu_map); do_stuff(); restart_other_cpus(stopped_cpus); ... } --- i386/include/smp.h: /* global data in i386/isa/apic_vector.s: */ extern volatile u_int stopped_cpus; extern volatile u_int started_cpus; extern u_int cpu_map; --- i386/isa/intr_machdep.h: #define XCPUSTOP_OFFSET 33 inthand_t Xcpustop; --- i386/i386/mp_machdep.c: /* * existing functions: */ mp_enable(u_int boot_addr) { ... #if defined( APIC_IO ) ... + /* install an inter-CPU IPI for CPU stop/restart */ + setidt(ICU_OFFSET + XCPUSTOP_OFFSET, Xcpustop, + SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); #endif /* APIC_IO */ ... } start_all_aps(u_int boot_addr) { ... /* start each AP */ for (x = 1; x <= mp_naps; ++x) { ... + cpu_map |= (1 << x); /* record AP in global map */ } ... + cpu_map |= 1; /* record BSP in global map */ } /* * new functions: */ /* * When called the executing CPU will send an IPI to all other CPUs * requesting that they halt execution. * * Usually (but not necessarily) called with 'cpu_map' as its arg. * * - Signals all CPUs in map to stop. * - Waits for each to stop. * * Returns: * -1: error * 0: NA * 1: ok * * XXX FIXME: this is not MP-safe, needs a lock to prevent multiple CPUs * from executing at same time. */ int stop_other_cpus( u_int map ) { if (!smp_active) return 0; stopped_cpus = 0; map &= ~(1 << cpuid); /* clear our bit */ /* send IPI to all CPUs in map */ selected_apic_ipi(map, ICU_OFFSET + XSTOP_CPUS_OFFSET, APIC_DELMODE_FIXED); while (stopped_cpus != map) /* spin */ ; return 1; } /* * Called by a CPU to restart stopped CPUs. * * Usually (but not necessarily) called with 'stopped_cpus' as its arg. * * - Signals all CPUs in map to restart. * - Waits for each to restart. * * Returns: * -1: error * 0: NA * 1: ok */ int restart_other_cpus( u_int map ) { if (!smp_active) return 0; map &= ~(1 << cpuid); /* XXX paranoia */ started_cpus = map; /* signal other cpus to restart */ while (started_cpus) /* wait for each to clear its bit */ /* spin */ ; return 1; } --- i386/isa/apic_vector.s: .globl _stopped_cpus _stopped_cpus: .long 0 .globl _started_cpus _started_cpus: .long 0 .globl _cpu_map _cpu_map: .long 0 /* * Executed by a CPU when it receives an Xcpustop IPI from another CPU, * * - Signals its receipt. * - Waits for permission to restart. * - Signals its restart. */ .text SUPERALIGN_TEXT .globl _Xcpustop _Xcpustop: pushl %eax pushl %ds /* save current data segment */ movl $KDSEL, %eax movl %ax, %ds /* use KERNEL data segment */ movl _cpuid, %eax /* id */ lock btsl %eax, _stopped_cpus /* stopped_cpus |= (1<<id) */ 1: btl %eax, _started_cpus /* while (!(started_cpus & (1<<id))) */ jnc 1b lock btrl %eax, _started_cpus /* started_cpus &= ~(1<<id) */ popl %ds /* restore previous data segment */ popl %eax iret ------------------------------------- cut ------------------------------------- -- Steve Passe | powered by smp@csn.net | Symmetric MultiProcessor FreeBSD
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199706260232.UAA17883>