summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2012-07-14 19:53:32 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2012-07-14 19:53:32 +0000
commit601eb04347145d4c38b46770929a1e9fc0992827 (patch)
treef9dcb9570f76352c75417f2c14c658b27b051eb0
parentaea0f3f6660b5a1bf2fa8be69b01257a54274c55 (diff)
A known errata of R4000 and R4400 processors, is that reading the internal
counter register close to a trigger of the counter interrupt, may cause the interrupt not to be generated. This makes it a bad idea to use the internal counter both for the scheduling clock and for delay(). Therefore, on IP22 systems (and IP28 because it makes my life easier), use one of the two 8254 timers connected to the onboard interrupt controller as the scheduling clock source. Adapted from NetBSD.
-rw-r--r--sys/arch/sgi/conf/GENERIC-IP225
-rw-r--r--sys/arch/sgi/conf/GENERIC-IP285
-rw-r--r--sys/arch/sgi/conf/RAMDISK-IP225
-rw-r--r--sys/arch/sgi/conf/RAMDISK-IP285
-rw-r--r--sys/arch/sgi/localbus/int.c78
-rw-r--r--sys/arch/sgi/sgi/mainbus.c7
6 files changed, 85 insertions, 20 deletions
diff --git a/sys/arch/sgi/conf/GENERIC-IP22 b/sys/arch/sgi/conf/GENERIC-IP22
index ac0e8ec1a0e..c1a3e37a674 100644
--- a/sys/arch/sgi/conf/GENERIC-IP22
+++ b/sys/arch/sgi/conf/GENERIC-IP22
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC-IP22,v 1.13 2012/05/26 17:10:07 miod Exp $
+# $OpenBSD: GENERIC-IP22,v 1.14 2012/07/14 19:53:27 miod Exp $
#
# THIS KERNEL IS FOR INDIGO (IP20), INDY (IP22) AND INDIGO2 (IP24) SYSTEMS ONLY.
#
@@ -44,9 +44,8 @@ config bsd swap generic
#
mainbus0 at root
cpu* at mainbus0
-clock0 at mainbus0
-int0 at mainbus0 # Interrupt Controller
+int0 at mainbus0 # Interrupt Controller and scheduling clock
imc0 at mainbus0 # Memory Controller
gio0 at imc0
eisa0 at imc0
diff --git a/sys/arch/sgi/conf/GENERIC-IP28 b/sys/arch/sgi/conf/GENERIC-IP28
index 8d0771c1bb4..72a13b3d69a 100644
--- a/sys/arch/sgi/conf/GENERIC-IP28
+++ b/sys/arch/sgi/conf/GENERIC-IP28
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC-IP28,v 1.2 2012/05/26 17:10:07 miod Exp $
+# $OpenBSD: GENERIC-IP28,v 1.3 2012/07/14 19:53:27 miod Exp $
#
# THIS KERNEL IS FOR POWER INDIGO2 R10000 (IP28) SYSTEMS ONLY.
#
@@ -36,9 +36,8 @@ config bsd swap generic
#
mainbus0 at root
cpu* at mainbus0
-clock0 at mainbus0
-int0 at mainbus0 # Interrupt Controller
+int0 at mainbus0 # Interrupt Controller and scheduling clock
imc0 at mainbus0 # Memory Controller
gio0 at imc0
eisa0 at imc0
diff --git a/sys/arch/sgi/conf/RAMDISK-IP22 b/sys/arch/sgi/conf/RAMDISK-IP22
index 959ad7a5b70..6ac8b3e9eb0 100644
--- a/sys/arch/sgi/conf/RAMDISK-IP22
+++ b/sys/arch/sgi/conf/RAMDISK-IP22
@@ -1,4 +1,4 @@
-# $OpenBSD: RAMDISK-IP22,v 1.10 2012/05/26 17:10:07 miod Exp $
+# $OpenBSD: RAMDISK-IP22,v 1.11 2012/07/14 19:53:27 miod Exp $
#
# THIS KERNEL IS FOR INDIGO (IP20), INDY (IP22) AND INDIGO2 (IP24) SYSTEMS ONLY.
@@ -52,9 +52,8 @@ config bsd root on rd0a swap on rd0b
#
mainbus0 at root
cpu* at mainbus0
-clock0 at mainbus0
-int0 at mainbus0 # Interrupt Controller
+int0 at mainbus0 # Interrupt Controller and scheduling clock
imc0 at mainbus0 # Memory Controller
gio0 at imc0
eisa0 at imc0
diff --git a/sys/arch/sgi/conf/RAMDISK-IP28 b/sys/arch/sgi/conf/RAMDISK-IP28
index 6ee95d4c8b4..a1c6b0a42be 100644
--- a/sys/arch/sgi/conf/RAMDISK-IP28
+++ b/sys/arch/sgi/conf/RAMDISK-IP28
@@ -1,4 +1,4 @@
-# $OpenBSD: RAMDISK-IP28,v 1.2 2012/05/26 17:10:07 miod Exp $
+# $OpenBSD: RAMDISK-IP28,v 1.3 2012/07/14 19:53:27 miod Exp $
#
# THIS KERNEL IS FOR POWER INDIGO2 R10000 (IP28) SYSTEMS ONLY.
@@ -44,9 +44,8 @@ config bsd root on rd0a swap on rd0b
#
mainbus0 at root
cpu* at mainbus0
-clock0 at mainbus0
-int0 at mainbus0 # Interrupt Controller
+int0 at mainbus0 # Interrupt Controller and scheduling clock
imc0 at mainbus0 # Memory Controller
gio0 at imc0
eisa0 at imc0
diff --git a/sys/arch/sgi/localbus/int.c b/sys/arch/sgi/localbus/int.c
index c97be27e52c..e47da144c46 100644
--- a/sys/arch/sgi/localbus/int.c
+++ b/sys/arch/sgi/localbus/int.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: int.c,v 1.4 2012/04/18 11:01:55 miod Exp $ */
+/* $OpenBSD: int.c,v 1.5 2012/07/14 19:53:29 miod Exp $ */
/* $NetBSD: int.c,v 1.24 2011/07/01 18:53:46 dyoung Exp $ */
/*
@@ -71,9 +71,12 @@ paddr_t int2_get_base(void);
#define int2_read(r) *(volatile uint8_t *)(int2_base + (r))
#define int2_write(r, v) *(volatile uint8_t *)(int2_base + (r)) = (v)
+void int_8254_cal(void);
+void int_8254_startclock(struct cpu_info *);
+uint32_t int_8254_intr0(uint32_t, struct trap_frame *);
+
/*
* INT2 Interrupt handling declarations: 16 local sources on 2 levels.
- * (we don't use the i8254 timer interrupts)
*
* In addition to this, INT3 provides 8 so-called mappable interrupts, which
* are cascaded to either one of the unused two INT2 VME interrupts.
@@ -240,9 +243,10 @@ int2_splx(int newipl)
struct cpu_info *ci = curcpu();
uint32_t sr;
- __asm__ ("\t.set noreorder\n");
+ __asm__ (".set noreorder");
ci->ci_ipl = newipl;
- __asm__ ("sync\n\t.set reorder\n");
+ __asm__ ("sync" ::: "memory");
+ __asm__ (".set reorder");
sr = disableintr(); /* XXX overkill? */
int2_write(INT2_LOCAL1_MASK, (int2_intem >> 8) & ~int2_l1imask[newipl]);
@@ -361,6 +365,8 @@ int2_attach(struct device *parent, struct device *self, void *aux)
int2_intr_establish(INT2_L1_INTR(INT2_L1_IP22_MAP1), IPL_TTY,
int2_mappable_intr, (void *)1, NULL);
}
+
+ int_8254_cal();
}
paddr_t
@@ -460,3 +466,67 @@ int2_intr_enable(void *v)
}
splx(s);
}
+
+/*
+ * A master clock is wired to TIMER_2, which in turn clocks the two other
+ * timers. The master frequency is 1MHz.
+ *
+ * TIMER_0 and TIMER_1 interrupt on HW_INT_2 and HW_INT_3, respectively.
+ *
+ * NB: Apparently int2 doesn't like counting down from one, but two works.
+ */
+
+static struct evcount int_clock_count;
+static int int_clock_irq = 2;
+
+void
+int_8254_cal(void)
+{
+ uint freq = 1000000 / 2 / hz;
+
+ /* Timer0 is our hz. */
+ int2_write(INT2_TIMER_CONTROL,
+ TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
+ int2_write(INT2_TIMER_0, freq & 0xff);
+ __asm__ ("sync" ::: "memory");
+ delay(4);
+ int2_write(INT2_TIMER_0, freq >> 8);
+
+ /* Timer2 clocks timer0 and timer1. */
+ int2_write(INT2_TIMER_CONTROL,
+ TIMER_SEL2 | TIMER_RATEGEN | TIMER_16BIT);
+ int2_write(INT2_TIMER_2, 2);
+ __asm__ ("sync" ::: "memory");
+ delay(4);
+ int2_write(INT2_TIMER_2, 0);
+
+ set_intr(INTPRI_CLOCK, CR_INT_2, int_8254_intr0);
+ evcount_attach(&int_clock_count, "clock", &int_clock_irq);
+ md_startclock = int_8254_startclock;
+}
+
+uint32_t
+int_8254_intr0(uint32_t hwpend, struct trap_frame *tf)
+{
+ struct cpu_info *ci = curcpu();
+
+ int2_write(INT2_TIMER_CLEAR, 0x01);
+ ci->ci_pendingticks++;
+ if (ci->ci_clock_started != 0) {
+ if (tf->ipl < IPL_CLOCK) {
+ while (ci->ci_pendingticks) {
+ int_clock_count.ec_count++;
+ hardclock(tf);
+ ci->ci_pendingticks--;
+ }
+ }
+ }
+
+ return hwpend;
+}
+
+void
+int_8254_startclock(struct cpu_info *ci)
+{
+ ci->ci_clock_started++;
+}
diff --git a/sys/arch/sgi/sgi/mainbus.c b/sys/arch/sgi/sgi/mainbus.c
index 0cb5fe14e57..4118f061fdc 100644
--- a/sys/arch/sgi/sgi/mainbus.c
+++ b/sys/arch/sgi/sgi/mainbus.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mainbus.c,v 1.10 2012/04/03 21:17:35 miod Exp $ */
+/* $OpenBSD: mainbus.c,v 1.11 2012/07/14 19:53:31 miod Exp $ */
/*
* Copyright (c) 2001-2003 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -99,9 +99,6 @@ mbattach(struct device *parent, struct device *self, void *aux)
caa.caa_hw = &bootcpu_hwinfo;
config_found(self, &caa, mbprint);
- caa.caa_maa.maa_name = "clock";
- config_found(self, &caa.caa_maa, mbprint);
-
switch (sys_config.system_type) {
#if defined(TGT_INDIGO) || defined(TGT_INDY) || defined(TGT_INDIGO2)
case SGI_IP20:
@@ -121,6 +118,8 @@ mbattach(struct device *parent, struct device *self, void *aux)
#endif
#ifdef TGT_O2
case SGI_O2:
+ caa.caa_maa.maa_name = "clock";
+ config_found(self, &caa.caa_maa, mbprint);
caa.caa_maa.maa_name = "macebus";
config_found(self, &caa.caa_maa, mbprint);
caa.caa_maa.maa_name = "gbe";