PERFORCE change 66921 for review
Peter Wemm
peter at FreeBSD.org
Sun Dec 12 15:41:30 PST 2004
http://perforce.freebsd.org/chv.cgi?CH=66921
Change 66921 by peter at peter_daintree on 2004/12/12 23:41:13
integrate i386 changes into amd64
Affected files ...
.. //depot/projects/hammer/sys/amd64/amd64/apic_vector.S#23 integrate
.. //depot/projects/hammer/sys/amd64/amd64/identcpu.c#36 integrate
.. //depot/projects/hammer/sys/amd64/amd64/legacy.c#16 integrate
.. //depot/projects/hammer/sys/amd64/amd64/mp_machdep.c#78 integrate
.. //depot/projects/hammer/sys/amd64/amd64/vm_machdep.c#58 integrate
.. //depot/projects/hammer/sys/amd64/conf/NOTES#51 integrate
.. //depot/projects/hammer/sys/amd64/include/apicvar.h#26 integrate
.. //depot/projects/hammer/sys/amd64/include/smp.h#18 integrate
.. //depot/projects/hammer/sys/amd64/pci/pci_cfgreg.c#16 integrate
Differences ...
==== //depot/projects/hammer/sys/amd64/amd64/apic_vector.S#23 (text+ko) ====
@@ -210,31 +210,16 @@
*/
.text
SUPERALIGN_TEXT
-IDTVEC(hardclock)
+IDTVEC(ipi_intr_bitmap_handler)
+
PUSH_FRAME
movq lapic, %rdx
movl $0, LA_EOI(%rdx) /* End Of Interrupt to APIC */
-
- call forwarded_hardclock
- MEXITCOUNT
- jmp doreti
-
-/*
- * Forward statclock to another CPU. Pushes a clockframe and calls
- * forwarded_statclock().
- */
- .text
- SUPERALIGN_TEXT
-IDTVEC(statclock)
- PUSH_FRAME
-
- movq lapic, %rdx
- movl $0, LA_EOI(%rdx) /* End Of Interrupt to APIC */
-
+
FAKE_MCOUNT(TF_RIP(%rsp))
- call forwarded_statclock
+ call ipi_bitmap_handler
MEXITCOUNT
jmp doreti
==== //depot/projects/hammer/sys/amd64/amd64/identcpu.c#36 (text+ko) ====
@@ -2,8 +2,6 @@
* Copyright (c) 1992 Terrence R. Lambert.
* Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
* Copyright (c) 1997 KATO Takenori.
- * Copyright (c) 2001 Tamotsu Hattori.
- * Copyright (c) 2001 Mitsuru IWASAKI.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
==== //depot/projects/hammer/sys/amd64/amd64/legacy.c#16 (text+ko) ====
==== //depot/projects/hammer/sys/amd64/amd64/mp_machdep.c#78 (text+ko) ====
@@ -131,6 +131,9 @@
} static cpu_info[MAXCPU];
static int cpu_apic_ids[MAXCPU];
+/* Holds pending bitmap based IPIs per CPU */
+static volatile u_int cpu_ipi_pending[MAXCPU];
+
static u_int boot_address;
static void set_logical_apic_ids(void);
@@ -296,25 +299,22 @@
int i;
/* Initialize the logical ID to APIC ID table. */
- for (i = 0; i < MAXCPU; i++)
+ for (i = 0; i < MAXCPU; i++) {
cpu_apic_ids[i] = -1;
+ cpu_ipi_pending[i] = 0;
+ }
/* Install an inter-CPU IPI for TLB invalidation */
setidt(IPI_INVLTLB, IDTVEC(invltlb), SDT_SYSIGT, SEL_KPL, 0);
setidt(IPI_INVLPG, IDTVEC(invlpg), SDT_SYSIGT, SEL_KPL, 0);
setidt(IPI_INVLRNG, IDTVEC(invlrng), SDT_SYSIGT, SEL_KPL, 0);
-
- /* Install an inter-CPU IPI for forwarding hardclock() */
- setidt(IPI_HARDCLOCK, IDTVEC(hardclock), SDT_SYSIGT, SEL_KPL, 0);
-
- /* Install an inter-CPU IPI for forwarding statclock() */
- setidt(IPI_STATCLOCK, IDTVEC(statclock), SDT_SYSIGT, SEL_KPL, 0);
/* Install an inter-CPU IPI for all-CPU rendezvous */
setidt(IPI_RENDEZVOUS, IDTVEC(rendezvous), SDT_SYSIGT, SEL_KPL, 0);
- /* Install an inter-CPU IPI for forcing an additional software trap */
- setidt(IPI_AST, IDTVEC(cpuast), SDT_SYSIGT, SEL_KPL, 0);
+ /* Install generic inter-CPU IPI handler */
+ setidt(IPI_BITMAP_VECTOR, IDTVEC(ipi_intr_bitmap_handler),
+ SDT_SYSIGT, SEL_KPL, 0);
/* Install an inter-CPU IPI for CPU stop/restart */
setidt(IPI_STOP, IDTVEC(cpustop), SDT_SYSIGT, SEL_KPL, 0);
@@ -876,21 +876,7 @@
* For statclock, we send an IPI to all CPU's to have them call this
* function.
*/
-void
-forwarded_statclock(struct clockframe frame)
-{
- struct thread *td;
- CTR0(KTR_SMP, "forwarded_statclock");
- td = curthread;
- td->td_intr_nesting_level++;
- if (profprocs != 0)
- profclock(&frame);
- if (pscnt == psdiv)
- statclock(&frame);
- td->td_intr_nesting_level--;
-}
-
void
forward_statclock(void)
{
@@ -913,18 +899,7 @@
* state and call hardclock_process() on the CPU receiving the clock interrupt
* and then just use a simple IPI to handle any ast's if needed.
*/
-void
-forwarded_hardclock(struct clockframe frame)
-{
- struct thread *td;
- CTR0(KTR_SMP, "forwarded_hardclock");
- td = curthread;
- td->td_intr_nesting_level++;
- hardclock_process(&frame);
- td->td_intr_nesting_level--;
-}
-
void
forward_hardclock(void)
{
@@ -940,6 +915,42 @@
ipi_selected(map, IPI_HARDCLOCK);
}
+
+void ipi_bitmap_handler(struct clockframe frame)
+{
+ int cpu = PCPU_GET(cpuid);
+ u_int ipi_bitmap;
+ struct thread *td;
+
+ ipi_bitmap = atomic_readandclear_int(&cpu_ipi_pending[cpu]);
+
+ critical_enter();
+
+ /* Nothing to do for AST */
+
+ if (ipi_bitmap & (1 << IPI_HARDCLOCK)) {
+ td = curthread;
+ td->td_intr_nesting_level++;
+ hardclock_process(&frame);
+ td->td_intr_nesting_level--;
+ }
+
+ if (ipi_bitmap & (1 << IPI_STATCLOCK)) {
+ CTR0(KTR_SMP, "forwarded_statclock");
+
+ td = curthread;
+ td->td_intr_nesting_level++;
+ if (profprocs != 0)
+ profclock(&frame);
+ if (pscnt == psdiv)
+ statclock(&frame);
+ td->td_intr_nesting_level--;
+ }
+
+ critical_exit();
+}
+
+
/*
* send an IPI to a set of cpus.
*/
@@ -947,15 +958,36 @@
ipi_selected(u_int32_t cpus, u_int ipi)
{
int cpu;
+ u_int bitmap = 0;
+ u_int old_pending;
+ u_int new_pending;
+ if (IPI_IS_BITMAPED(ipi)) {
+ bitmap = 1 << ipi;
+ ipi = IPI_BITMAP_VECTOR;
+ }
+
CTR3(KTR_SMP, "%s: cpus: %x ipi: %x", __func__, cpus, ipi);
while ((cpu = ffs(cpus)) != 0) {
cpu--;
+ cpus &= ~(1 << cpu);
+
KASSERT(cpu_apic_ids[cpu] != -1,
("IPI to non-existent CPU %d", cpu));
+
+ if (bitmap) {
+ do {
+ old_pending = cpu_ipi_pending[cpu];
+ new_pending = old_pending | bitmap;
+ } while (!atomic_cmpset_int(&cpu_ipi_pending[cpu],old_pending, new_pending));
+
+ if (old_pending)
+ continue;
+ }
+
lapic_ipi_vectored(ipi, cpu_apic_ids[cpu]);
- cpus &= ~(1 << cpu);
}
+
}
/*
==== //depot/projects/hammer/sys/amd64/amd64/vm_machdep.c#58 (text+ko) ====
@@ -57,6 +57,7 @@
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
+#include <sys/pioctl.h>
#include <sys/proc.h>
#include <sys/sf_buf.h>
#include <sys/smp.h>
@@ -128,6 +129,17 @@
td2->td_frame->tf_rdx = 1;
/*
+ * If the parent process has the trap bit set (i.e. a debugger had
+ * single stepped the process to the system call), we need to clear
+ * the trap flag from the new frame unless the debugger had set PF_FORK
+ * on the parent. Otherwise, the child will receive a (likely
+ * unexpected) SIGTRAP when it executes the first instruction after
+ * returning to userland.
+ */
+ if ((p1->p_pfsflags & PF_FORK) == 0)
+ td2->td_frame->tf_eflags &= ~PSL_T;
+
+ /*
* Set registers for trampoline to user mode. Leave space for the
* return address on stack. These are the kernel mode register values.
*/
==== //depot/projects/hammer/sys/amd64/conf/NOTES#51 (text+ko) ====
@@ -4,7 +4,7 @@
# This file contains machine dependent kernel configuration notes. For
# machine independent notes, look in /sys/conf/NOTES.
#
-# (XXX from i386:NOTES,v 1.1176)
+# (XXX from i386:NOTES,v 1.1177)
# $FreeBSD: src/sys/amd64/conf/NOTES,v 1.20 2004/09/22 01:04:54 peter Exp $
#
@@ -240,8 +240,10 @@
#XXX#device ed
#XXX#device lnc
-#XXX#device ath
-#XXX#device ath_hal # Atheros HAL (includes binary component)
+device ath
+device ath_hal # Atheros HAL (includes binary component)
+device ath_rate_onoe # Onoe rate control for ath driver
+#device ath_rate_amrr # AMRR rate control for ath driver
device wlan # 802.11 layer
#
==== //depot/projects/hammer/sys/amd64/include/apicvar.h#26 (text+ko) ====
@@ -83,21 +83,54 @@
#define APIC_IO_INTS (IDT_IO_INTS + 16)
#define APIC_NUM_IOINTS 192
+/*
+ ********************* !!! WARNING !!! ******************************
+ * Each local apic has an interrupt receive fifo that is two entries deep
+ * for each interrupt priority class (higher 4 bits of interrupt vector).
+ * Once the fifo is full the APIC can no longer receive interrupts for this
+ * class and sending IPIs from other CPUs will be blocked.
+ * To avoid deadlocks there should be no more than two IPI interrupts
+ * pending at the same time.
+ * Currently this is guaranteed by dividing the IPIs in two groups that have
+ * each at most one IPI interrupt pending. The first group is protected by the
+ * smp_ipi_mtx and waits for the completion of the IPI (Only one IPI user
+ * at a time) The second group uses a single interrupt and a bitmap to avoid
+ * redundant IPI interrupts.
+ *
+ * Right now IPI_STOP used by kdb shares the interrupt priority class with
+ * the two IPI groups mentioned above. As such IPI_STOP may cause a deadlock.
+ * Eventually IPI_STOP should use NMI IPIs - this would eliminate this and
+ * other deadlocks caused by IPI_STOP.
+ */
+
#define APIC_LOCAL_INTS 240
-#define APIC_TIMER_INT APIC_LOCAL_INTS
-#define APIC_ERROR_INT (APIC_LOCAL_INTS + 1)
-#define APIC_THERMAL_INT (APIC_LOCAL_INTS + 2)
+
+#if 0
+#define APIC_TIMER_INT (APIC_LOCAL_INTS + X)
+#define APIC_ERROR_INT (APIC_LOCAL_INTS + X)
+#define APIC_THERMAL_INT (APIC_LOCAL_INTS + X)
+#endif
-#define APIC_IPI_INTS (APIC_LOCAL_INTS + 3)
-#define IPI_AST APIC_IPI_INTS /* Generate software trap. */
+#define APIC_IPI_INTS (APIC_LOCAL_INTS + 0)
+#define IPI_RENDEZVOUS (APIC_IPI_INTS) /* Inter-CPU rendezvous. */
#define IPI_INVLTLB (APIC_IPI_INTS + 1) /* TLB Shootdown IPIs */
#define IPI_INVLPG (APIC_IPI_INTS + 2)
#define IPI_INVLRNG (APIC_IPI_INTS + 3)
-#define IPI_HARDCLOCK (APIC_IPI_INTS + 8) /* Inter-CPU clock handling. */
-#define IPI_STATCLOCK (APIC_IPI_INTS + 9)
-#define IPI_RENDEZVOUS (APIC_IPI_INTS + 10) /* Inter-CPU rendezvous. */
-#define IPI_STOP (APIC_IPI_INTS + 11) /* Stop CPU until restarted. */
+/* Vector to handle bitmap based IPIs */
+#define IPI_BITMAP_VECTOR (APIC_IPI_INTS + 5)
+
+/* IPIs handled by IPI_BITMAPED_VECTOR (XXX ups is there a better place?) */
+#define IPI_AST 0 /* Generate software trap. */
+#define IPI_HARDCLOCK 1 /* Inter-CPU clock handling. */
+#define IPI_STATCLOCK 2
+#define IPI_BITMAP_LAST IPI_STATCLOCK
+#define IPI_IS_BITMAPED(x) ((x) <= IPI_BITMAP_LAST)
+
+#define IPI_STOP (APIC_IPI_INTS + 6) /* Stop CPU until restarted. */
+/* The spurious interrupt can share the priority class with the IPIs since
+ * it is not a normal interrupt. (Does not use the APIC's interrupt fifo)
+ */
#define APIC_SPURIOUS_INT 255
#define LVT_LINT0 0
==== //depot/projects/hammer/sys/amd64/include/smp.h#18 (text+ko) ====
@@ -40,9 +40,7 @@
IDTVEC(invltlb), /* TLB shootdowns - global */
IDTVEC(invlpg), /* TLB shootdowns - 1 page */
IDTVEC(invlrng), /* TLB shootdowns - page range */
- IDTVEC(hardclock), /* Forward hardclock() */
- IDTVEC(statclock), /* Forward statclock() */
- IDTVEC(cpuast), /* Additional software trap on other cpu */
+ IDTVEC(ipi_intr_bitmap_handler), /* Bitmap based IPIs */
IDTVEC(cpustop), /* CPU stops & waits to be restarted */
IDTVEC(rendezvous); /* handle CPU rendezvous */
@@ -54,9 +52,8 @@
void ipi_all_but_self(u_int ipi);
void ipi_self(u_int ipi);
void forward_statclock(void);
-void forwarded_statclock(struct clockframe frame);
void forward_hardclock(void);
-void forwarded_hardclock(struct clockframe frame);
+void ipi_bitmap_handler(struct clockframe frame);
u_int mp_bootaddress(u_int);
int mp_grab_cpu_hlt(void);
void mp_topology(void);
==== //depot/projects/hammer/sys/amd64/pci/pci_cfgreg.c#16 (text+ko) ====
More information about the p4-projects
mailing list