* Copyright(c) By Marco Munari. All right reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
* 3. Neither the name of allerta nor the names of its contributors
*    may be used to endorse or promote products derived from this software
*    without specific prior written permission.
*
* SOURCE CODE PROVIDED ``AS IS'' WITHOUT WARRANTIES, BUT WITH CARE.

This patch it's only a sensible speed up for i386, i486, i586,
Athlon K7, K8 compatibility mode and Pentium I to IV architectures,
with an exception of NSC (National Semiconductor) GEODE GX1,
which is supposed to have a timer latch bug, and was the reason for
the (slow) latch fix (a speed up also for GEODE is included).

add  option NOBROKENLATCH  to obtain the 0.7% performance increase.

explanation:
gettick() is a function called a lot (even more than 4096 times each second),
with this patch it is faster and lighter.

20:27:35 mar@nb:/home/mar/oldkernel/$ profile gettick
                2.42        0.00 86732026/86732026     gettick [103]
[103]    0.2    2.42        0.00 86732026         gettick [103]
  0.2    1230.30     2.42 86732026     0.00     0.00  gettick [103]
 [103] gettick             [136] sched_sync         [1149] uvm_vnp_sync       
20:27:39 mar@nb:/home/mar/oldkernel/$ profile gettick
                2.43        0.00 87409410/87409410     gettick [104]
[104]    0.2    2.43        0.00 87409410         gettick [104]
  0.2    1200.07     2.43 87409410     0.00     0.00  gettick [104]
 [104] gettick             [136] sched_sync         [1149] uvm_vnp_sync       
20:30:24 mar@nb:/home/mar/oldkernel/$


for me now it produces the following code (in the object file clock.o),
wich is about 5 times faster, and so short that can be placed inline...:
00000184 <gettick>:
 184:   55                      push   %ebp
 185:   89 e5                   mov    %esp,%ebp
 187:   e8 fc ff ff ff          call   188 <gettick+0x4>  ;profiling template

;belove code can also be placed inline
;(only 9 bytes longer than the ``inline'' call)
 18c:   31 c0                   xor    %eax,%eax
 18e:   fa                      cli    
 18f:   e6 43                   out    %al,$0x43
 191:   e4 40                   in     $0x40,%al
 193:   88 c4                   mov    %al,%ah
 195:   e4 40                   in     $0x40,%al
 197:   fb                      sti    
 198:   86 c4                   xchg   %al,%ah
;end of possibly inline code

 19a:   5d                      pop    %ebp
 19b:   c3                      ret    

before it was:
d03f6e90 <gettick>:
d03f6e90:       55                      push   %ebp
d03f6e91:       89 e5                   mov    %esp,%ebp
d03f6e93:       57                      push   %edi
d03f6e94:       56                      push   %esi
d03f6e95:       53                      push   %ebx
d03f6e96:       83 ec 10                sub    $0x10,%esp
d03f6e99:       e8 72 80 07 00          call   d046ef10 <__mcount>
d03f6e9e:       83 3d 64 88 63 d0 00    cmpl   $0x0,0xd0638864
d03f6ea5:       0f 84 c7 00 00 00       je     d03f6f72 <gettick+0xe2>
d03f6eab:       fa                      cli    
d03f6eac:       e4 40                   in     $0x40,%al
d03f6eae:       0f b6 f8                movzbl %al,%edi
d03f6eb1:       e4 40                   in     $0x40,%al
d03f6eb3:       0f b6 c0                movzbl %al,%eax
d03f6eb6:       c1 e0 08                shl    $0x8,%eax
d03f6eb9:       09 c7                   or     %eax,%edi
d03f6ebb:       e4 40                   in     $0x40,%al
d03f6ebd:       0f b6 f0                movzbl %al,%esi
d03f6ec0:       e4 40                   in     $0x40,%al
d03f6ec2:       0f b6 c0                movzbl %al,%eax
d03f6ec5:       c1 e0 08                shl    $0x8,%eax
d03f6ec8:       09 c6                   or     %eax,%esi
d03f6eca:       e4 40                   in     $0x40,%al
d03f6ecc:       0f b6 c0                movzbl %al,%eax
d03f6ecf:       89 45 f0                mov    %eax,0xfffffff0(%ebp)
d03f6ed2:       e4 40                   in     $0x40,%al
d03f6ed4:       0f b6 c0                movzbl %al,%eax
d03f6ed7:       c1 e0 08                shl    $0x8,%eax
d03f6eda:       09 45 f0                or     %eax,0xfffffff0(%ebp)
d03f6edd:       fb                      sti    
d03f6ede:       39 f7                   cmp    %esi,%edi
d03f6ee0:       7c 1b                   jl     d03f6efd <gettick+0x6d>
d03f6ee2:       3b 75 f0                cmp    0xfffffff0(%ebp),%esi
d03f6ee5:       7c 12                   jl     d03f6ef9 <gettick+0x69>
d03f6ee7:       89 f8                   mov    %edi,%eax
d03f6ee9:       89 f2                   mov    %esi,%edx
d03f6eeb:       2b 45 f0                sub    0xfffffff0(%ebp),%eax
d03f6eee:       3d ff 01 00 00          cmp    $0x1ff,%eax
d03f6ef3:       0f 8e 90 00 00 00       jle    d03f6f89 <gettick+0xf9>
d03f6ef9:       39 f7                   cmp    %esi,%edi
d03f6efb:       7d 06                   jge    d03f6f03 <gettick+0x73>
d03f6efd:       89 f8                   mov    %edi,%eax
d03f6eff:       89 f7                   mov    %esi,%edi
d03f6f01:       89 c6                   mov    %eax,%esi
d03f6f03:       3b 75 f0                cmp    0xfffffff0(%ebp),%esi
d03f6f06:       7d 08                   jge    d03f6f10 <gettick+0x80>
d03f6f08:       89 f0                   mov    %esi,%eax
d03f6f0a:       8b 75 f0                mov    0xfffffff0(%ebp),%esi
d03f6f0d:       89 45 f0                mov    %eax,0xfffffff0(%ebp)
d03f6f10:       39 f7                   cmp    %esi,%edi
d03f6f12:       7d 06                   jge    d03f6f1a <gettick+0x8a>
d03f6f14:       89 f8                   mov    %edi,%eax
d03f6f16:       89 f7                   mov    %esi,%edi
d03f6f18:       89 c6                   mov    %eax,%esi
d03f6f1a:       89 f8                   mov    %edi,%eax
d03f6f1c:       89 f2                   mov    %esi,%edx
d03f6f1e:       2b 45 f0                sub    0xfffffff0(%ebp),%eax
d03f6f21:       3d ff 01 00 00          cmp    $0x1ff,%eax
d03f6f26:       7e 61                   jle    d03f6f89 <gettick+0xf9>
d03f6f28:       89 f0                   mov    %esi,%eax
d03f6f2a:       8b 15 c0 d0 52 d0       mov    0xd052d0c0,%edx
d03f6f30:       bb 02 00 00 00          mov    $0x2,%ebx
d03f6f35:       2b 45 f0                sub    0xfffffff0(%ebp),%eax
d03f6f38:       89 55 e8                mov    %edx,0xffffffe8(%ebp)
d03f6f3b:       8b 4d f0                mov    0xfffffff0(%ebp),%ecx
d03f6f3e:       89 45 ec                mov    %eax,0xffffffec(%ebp)
d03f6f41:       29 f9                   sub    %edi,%ecx
d03f6f43:       89 d0                   mov    %edx,%eax
d03f6f45:       99                      cltd   
d03f6f46:       f7 fb                   idiv   %ebx
d03f6f48:       89 45 e4                mov    %eax,0xffffffe4(%ebp)
d03f6f4b:       05 de 34 12 00          add    $0x1234de,%eax
d03f6f50:       99                      cltd   
d03f6f51:       f7 7d e8                idivl  0xffffffe8(%ebp)
d03f6f54:       8d 04 08                lea    (%eax,%ecx,1),%eax
d03f6f57:       89 f9                   mov    %edi,%ecx
d03f6f59:       29 f1                   sub    %esi,%ecx
d03f6f5b:       39 45 ec                cmp    %eax,0xffffffec(%ebp)
d03f6f5e:       7c 07                   jl     d03f6f67 <gettick+0xd7>
d03f6f60:       89 fa                   mov    %edi,%edx
d03f6f62:       39 4d ec                cmp    %ecx,0xffffffec(%ebp)
d03f6f65:       eb 04                   jmp    d03f6f6b <gettick+0xdb>
d03f6f67:       89 f2                   mov    %esi,%edx
d03f6f69:       39 c8                   cmp    %ecx,%eax
d03f6f6b:       7d 1c                   jge    d03f6f89 <gettick+0xf9>
d03f6f6d:       8b 55 f0                mov    0xfffffff0(%ebp),%edx
d03f6f70:       eb 17                   jmp    d03f6f89 <gettick+0xf9>
d03f6f72:       fa                      cli    
d03f6f73:       31 c0                   xor    %eax,%eax
d03f6f75:       e6 43                   out    %al,$0x43
d03f6f77:       e4 40                   in     $0x40,%al
d03f6f79:       89 c1                   mov    %eax,%ecx
d03f6f7b:       e4 40                   in     $0x40,%al
d03f6f7d:       fb                      sti    
d03f6f7e:       0f b6 d0                movzbl %al,%edx
d03f6f81:       0f b6 c1                movzbl %cl,%eax
d03f6f84:       c1 e2 08                shl    $0x8,%edx
d03f6f87:       09 c2                   or     %eax,%edx
d03f6f89:       83 c4 10                add    $0x10,%esp
d03f6f8c:       89 d0                   mov    %edx,%eax
d03f6f8e:       5b                      pop    %ebx
d03f6f8f:       5e                      pop    %esi
d03f6f90:       5f                      pop    %edi
d03f6f91:       5d                      pop    %ebp
d03f6f92:       c3                      ret    


--- OpenBSD/sys/arch/i386/isa/clock.c	13 Jun 2004 22:49:16 +0100	1.32
+++ sys/arch/i386/isa/clock.c	23 Jan 2006 13:27:58 +0000	
@@ -82,6 +82,27 @@
 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
 
+
+/* 
+ * improvements
+ * copyright (c) 2005, 2006 by Marco Munari <mar.develops allerta.it>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of allerta nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * SOURCE CODE PROVIDED ``AS IS'' WITHOUT WARRANTIES, BUT WITH CARE.
+ *
+ */
+
 /*
  * Primitive clock interrupt routines.
  */
@@ -147,7 +168,7 @@
 #if defined(I586_CPU) || defined(I686_CPU)
 int pentium_mhz;
 #endif
-#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
+#if (defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)) && !defined(NOBROKENLATCH) 
 int clock_broken_latch;
 #endif
 
@@ -260,13 +281,15 @@
 gettick()
 {
 
-#if defined(I586_CPU) || defined(I686_CPU)
+#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(NOBROKENLATCH)
 	if (clock_broken_latch) {
+		/* NSC(National Semiconductor) Geode GX1 CPU Family 5 */
 		int v1, v2, v3;
 		int w1, w2, w3;
 
 		disable_intr();
 
+		/*
 		v1 = inb(TIMER_CNTR0);
 		v1 |= inb(TIMER_CNTR0) << 8;
 		v2 = inb(TIMER_CNTR0);
@@ -274,24 +297,54 @@
 		v3 = inb(TIMER_CNTR0);
 		v3 |= inb(TIMER_CNTR0) << 8;
 
+  %   cumulative   self              self     total           
+ time   seconds   seconds    calls  ms/call  ms/call  name    
+  0.8    2315.93    22.21 528695304     0.00     0.00  gettick [76]
+
+		*/
+		/* WARNING: NEVER TESTED */
+		__asm__ __volatile (
+				    	"inb %1,%%al\n"
+				    "	movb %%al,%%ah\n"
+				    "	inb %1,%%al\n"
+				    "	xchgb %%al,%%ah\n"
+				    "	movzwl %%ax,%0\n"
+				    :"=r" (v1) /* %0 */
+				    :"N" (TIMER_CNTR0) /* %1 */
+				    :"%ax");
+		__asm__ __volatile ( /* XXX define a macro! */
+				    	"inb %1,%%al\n"
+				    "	movb %%al,%%ah\n"
+				    "	inb %1,%%al\n"
+				    "	xchgb %%al,%%ah\n"
+				    "	movzwl %%ax,%0\n"
+				    :"=ri" (v2) /* the difference */
+				    :"N" (TIMER_CNTR0)
+				    :"%ax");
+		__asm__ __volatile (
+				    	"inb %1,%%al\n"
+				    "	movb %%al,%%ah\n"
+				    "	inb %1,%%al\n"
+				    "	xchgb %%al,%%ah\n"
+				    "	movzwl %%ax,%0\n"
+				    :"=r" (v3) /* the difference */
+				    :"N" (TIMER_CNTR0)
+				    :"%ax");
 		enable_intr();
 
 		if (v1 >= v2 && v2 >= v3 && v1 - v3 < 0x200)
 			return (v2);
 
-#define _swap_val(a, b) do { \
-	int c = a; \
-	a = b; \
-	b = c; \
-} while (0)
+#define _swap_val(a, b)							\
+		__asm __volatile ("xchgl %0,%1" :"+r" (a), "+ri" (b));
 
 		/* sort v1 v2 v3 */
 		if (v1 < v2)
-			_swap_val(v1, v2);
+			_swap_val(v2, v1);
 		if (v2 < v3)
 			_swap_val(v2, v3);
 		if (v1 < v2)
-			_swap_val(v1, v2);
+			_swap_val(v2, v1);
 
 		/* compute the middle value */
 		if (v1 - v3 < 0x200)
@@ -310,6 +363,30 @@
 	} else
 #endif
 	{
+#if defined(__GNUC__)
+		({
+		int tmp;
+		__asm __volatile(
+				 "	xorl %%eax,%%eax\n"
+# if TIMER_SEL0!=0 || TIMER_LATCH!=0  /* not valid syntax, just in theory */
+				 "	movb TIMER_SEL0 | TIMER_LATCH,%%al"
+# endif
+				 "	cli\n"
+				 "	outb %%al,%1\n"
+				 "	inb %2,%%al\n"
+				 "	movb %%al,%%ah\n"
+				 "	inb %2,%%al\n"
+				 "	sti\n"
+				 "	xchgb %%al,%%ah\n"
+				 :"=a" (tmp)	     /* %0 */
+				 :"N" (TIMER_MODE)   /* %1 */,
+				 "N" (TIMER_CNTR0)   /* %2 */
+				 //:"%eax"
+			);
+			return tmp;
+		});
+/* __GNUC__ */
+#else  /* !__GNUC__ */
 		u_char lo, hi;
 
 		disable_intr();
@@ -320,6 +397,7 @@
 
 		enable_intr();
 		return ((hi << 8) | lo);
+#endif  /* !__GNUC__ */
 	}
 }
 
@@ -576,7 +654,12 @@
 	splx(s);
 	if (!cmoscentury) {
 #ifdef DIAGNOSTIC
-		printf("clock: unknown CMOS layout\n");
+		unsigned short i;
+
+		printf("clock: unknown CMOS layout [");
+		for (i=0 ; i<mc146818_read(NULL,MC_NREGS-1) ; i++)
+			printf(" %x",mc146818_read(NULL, i));
+		printf("]\n");
 #endif
 		return (clockyear);
 	}
--- OpenBSD/sys/arch/i386/i386/machdep.c	Mon Jan 23 19:27:55 2006
+++ sys/arch/i386/i386/machdep.c	Mon Jan 23 16:30:20 2006
@@ -74,6 +74,26 @@
  *	@(#)machdep.c	7.4 (Berkeley) 6/3/91
  */
 
+/* 
+ * extra improvements
+ * copyright (c) 2005, 2006 by Marco Munari <mar.develops allerta.it>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of allerta nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * SOURCE CODE PROVIDED ``AS IS'' WITHOUT WARRANTIES, BUT WITH CARE.
+ *
+ */
+
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/signalvar.h>
@@ -585,6 +605,7 @@
 
 	size = MAXBSIZE * nbuf;
 	if (uvm_map(kernel_map, (vaddr_t *) &buffers, round_page(size),
+	//if (uvm_map(kernel_map, &buffers, round_page(size),
 		    NULL, UVM_UNKNOWN_OFFSET, 0,
 		    UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE,
 				UVM_ADV_NORMAL, 0)))
@@ -1280,8 +1301,9 @@
 cyrix6x86_cpu_setup(struct cpu_info *ci)
 {
 #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
+# ifndef NOBROKENLATCH
 	extern int clock_broken_latch;
-
+# endif
 	switch ((ci->ci_signature >> 4) & 15) { /* model */
 	case -1: /* M1 w/o cpuid */
 	case 2:	/* M1 */
@@ -1303,7 +1325,9 @@
 		break;	/* fallthrough? */
 	case 4:	/* GXm */
 		/* Unset the TSC bit until calibrate_delay() gets fixed. */
+# ifndef NOBROKENLATCH
 		clock_broken_latch = 1;
+# endif
 		curcpu()->ci_feature_flags &= ~CPUID_TSC;
 		printf("%s: TSC disabled\n", ci->ci_dev.dv_xname);
 		break;
@@ -1340,11 +1364,15 @@
 void
 natsem6x86_cpu_setup(struct cpu_info *ci)
 {
-#if defined(I586_CPU) || defined(I686_CPU)
+#if (defined(I586_CPU) || defined(I686_CPU))
+# ifdef NOBROKENLATCH
+	panic("NOBROKENLATCH but the timer latch has to be supposed broken\n");
+# else
 	extern int clock_broken_latch;
-	int model = (ci->ci_signature >> 4) & 15;
 
 	clock_broken_latch = 1;
+# endif
+	int model = (ci->ci_signature >> 4) & 15;
 	switch (model) {
 	case 4:
 		cpu_feature &= ~CPUID_TSC;
--- OpenBSD/share/man/man4/options.4	07 Dec 2005 04:11:23 +0100	1.173
+++ share/man/man4/options.4	15 Feb 2006 17:40:20 +0100	
@@ -999,6 +999,12 @@
 When enabled, it speeds up interrupt processing by removing delays
 while accessing the interrupt controller.
 Care should be taken when using this option.
+.It Cd option NOBROKENLATCH
+This option (interesting only for i386 architectures) *clean* the
+runtime consuming fix, which was necessary in practice only for National
+Semiconductor Geode family 5 (586) based motherboards.
+This option create lightly less generic code. If timer latch is really
+broken the machine time will not progress as your watch.
 .It Cd option APM_NOPRINT
 This option is supported on the i386 architecture.
 When enabled, kernel messages regarding the status of the automatic power
