diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2012-07-14 19:53:32 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2012-07-14 19:53:32 +0000 |
commit | 601eb04347145d4c38b46770929a1e9fc0992827 (patch) | |
tree | f9dcb9570f76352c75417f2c14c658b27b051eb0 /sys/arch | |
parent | aea0f3f6660b5a1bf2fa8be69b01257a54274c55 (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.
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/sgi/conf/GENERIC-IP22 | 5 | ||||
-rw-r--r-- | sys/arch/sgi/conf/GENERIC-IP28 | 5 | ||||
-rw-r--r-- | sys/arch/sgi/conf/RAMDISK-IP22 | 5 | ||||
-rw-r--r-- | sys/arch/sgi/conf/RAMDISK-IP28 | 5 | ||||
-rw-r--r-- | sys/arch/sgi/localbus/int.c | 78 | ||||
-rw-r--r-- | sys/arch/sgi/sgi/mainbus.c | 7 |
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"; |