summaryrefslogtreecommitdiff
path: root/sys/arch/i386
diff options
context:
space:
mode:
authorMichael Shalayeff <mickey@cvs.openbsd.org>1998-05-13 19:49:26 +0000
committerMichael Shalayeff <mickey@cvs.openbsd.org>1998-05-13 19:49:26 +0000
commit4004b43497a804047215084c5ccd26a0c08ec0ce (patch)
tree071750dd260c1e664b110c84a9b4234e1e351921 /sys/arch/i386
parentac2c89bf61167c1418043fdb45c252c1e3e62077 (diff)
making kernel, drinking LI tea and writing an opus magnum enspired
by the freebsd commit logs: first of all i should state that we are the only os that uses pentium counters in their microtime (freebsd, netbsd, etc checked). the bug fixed derives from the fact that #UD (divide by zero) is generated in two cases: a) divide by zero; b) divide overflow. so, the later case was the one causing panics on reboot. due to the divl insn design in the intel processors, the possible sizes of operands and results are: 16/8=8,8; 32/16=16,16; 64/32=32,32. the division will generate an #UD exception when the quotient won't fit into result, that is 32bit in our case (64bit is divided on 32bit). problem solved by normalizing the dividend by the divisor, so the quotient would not result a divide overflow. tested by: mickey, gene, mickey. talked over: mickey, gene, marc, maillists, mickey.
Diffstat (limited to 'sys/arch/i386')
-rw-r--r--sys/arch/i386/i386/microtime.s21
1 files changed, 15 insertions, 6 deletions
diff --git a/sys/arch/i386/i386/microtime.s b/sys/arch/i386/i386/microtime.s
index 27b417abe52..6234c91f9ae 100644
--- a/sys/arch/i386/i386/microtime.s
+++ b/sys/arch/i386/i386/microtime.s
@@ -1,4 +1,4 @@
-/* $OpenBSD: microtime.s,v 1.10 1997/12/30 23:35:19 mickey Exp $ */
+/* $OpenBSD: microtime.s,v 1.11 1998/05/13 19:49:25 mickey Exp $ */
/* $NetBSD: microtime.s,v 1.16 1995/04/17 12:06:47 cgd Exp $ */
/*-
@@ -57,6 +57,7 @@ ENTRY(microtime)
#endif
movb $(TIMER_SEL0|TIMER_LATCH),%al
+ pushfl
cli # disable interrupts
outb %al,$TIMER_MODE # latch timer 0's counter
@@ -125,7 +126,7 @@ common_microtime:
movl _time,%edx # get time.tv_sec
addl _time+4,%eax # add time.tv_usec
- sti # enable interrupts
+ popfl # enable interrupts
cmpl $1000000,%eax # carry in timeval?
jb 3f
@@ -147,14 +148,22 @@ common_microtime:
#if defined (NTP)
.align 2, 0x90
pentium_microtime:
+ pushfl
cli
.byte 0x0f, 0x31 # RDTSC
subl _pentium_base_tsc,%eax
sbbl _pentium_base_tsc+4,%edx
- orl %ecx, %ecx
- jnz 1f
- incl %ecx
-1: divl %ecx # convert to usec
+ /*
+ * correct the high word first so we won't
+ * receive a result overflow aka div/0 fault
+ */
+ pushl %eax
+ movl %edx, %eax
+ shll $16, %edx
+ divw %cx
+ movzwl %dx, %edx
+ popl %eax
+ divl %ecx
jmp common_microtime
#endif
#endif