a20: try to avoid io_delay if A20 is already enabled
authorH. Peter Anvin <hpa@linux.intel.com>
Tue, 21 Apr 2009 23:08:07 +0000 (16:08 -0700)
committerH. Peter Anvin <hpa@linux.intel.com>
Tue, 21 Apr 2009 23:08:07 +0000 (16:08 -0700)
We have at least the possibility to avoid io_delay if A20 is already
enabled.  Thus, give it a try.  Furthermore, when calling enable_a20,
always try the zero-work case first, since we may have been enabled by
a previous call.  This should improve performance of the rm/pm
ping-pong.

Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
core/bcopy32.inc

index c4edc71..f2cc6ca 100644 (file)
@@ -193,13 +193,6 @@ simple_pm_call:
 %define IO_DELAY_PORT  80h             ; Invalid port (we hope!)
 %define disable_wait   32              ; How long to wait for a disable
 
-; Note the skip of 2 here
-%define A20_DUNNO      0               ; A20 type unknown
-%define A20_NONE       2               ; A20 always on?
-%define A20_BIOS       4               ; A20 BIOS enable
-%define A20_KBC                6               ; A20 through KBC
-%define A20_FAST       8               ; A20 through port 92h
-
 slow_out:      out dx, al              ; Fall through
 
 _io_delay:     out IO_DELAY_PORT,al
@@ -228,22 +221,19 @@ try_enable_a20:
 %endif
 
 ;
-; If the A20 type is known, jump straight to type
-;
-               jmp word [cs:A20Ptr]
-
-;
-; First, see if we are on a system with no A20 gate
+; First, see if we are on a system with no A20 gate, or the A20 gate
+; is already enabled for us...
 ;
-a20_dunno:
 a20_none:
-               mov word [cs:A20Ptr], a20_none
                call a20_test
                jnz a20_done
+               ; Otherwise, see if we had something memorized...
+               jmp word [cs:A20Ptr]
 
 ;
 ; Next, try the BIOS (INT 15h AX=2401h)
 ;
+a20_dunno:
 a20_bios:
                mov word [cs:A20Ptr], a20_bios
                mov ax,2401h
@@ -337,20 +327,24 @@ a20_done: popad
 ; This routine tests if A20 is enabled (ZF = 0).  This routine
 ; must not destroy any register contents.
 ;
+; The no-write early out avoids the io_delay in the (presumably common)
+; case of A20 already enabled (e.g. from a previous call.)
+;
 a20_test:
                push es
                push cx
-               push ax
-               mov cx,0FFFFh           ; HMA = segment 0FFFFh
+               push eax
+               mov cx,0FFFFh                   ; HMA = segment 0FFFFh
                mov es,cx
-               mov cx,32               ; Loop count
-               mov ax,[cs:A20Test]
-.a20_wait:     inc ax
-               mov [cs:A20Test],ax
-               io_delay                ; Serialize, and fix delay
-               cmp ax,[es:A20Test+10h]
-               loopz .a20_wait
-.a20_done:     pop ax
+               mov eax,[cs:A20Test]
+               mov cx,32                       ; Loop count
+               jmp .test                       ; First iteration = early out
+.wait:         inc eax
+               mov [cs:A20Test],eax
+               io_delay                        ; Serialize, and fix delay
+.test:         cmp eax,[es:A20Test+10h]
+               loopz .wait
+.done:         pop eax
                pop cx
                pop es
                ret