aufziehvogel
aufziehvogel

Reputation: 7287

Why do we need to disable interrupts when enabling A20 sometimes?

In some pieces of code on the OSDev wiki for enabling the A20 line, we have cli interrupts commands. In some others we do not have them.

E.g. when setting the A20 line through the old keyboard controller method, the whole code is surrounded by a cli and sti combination. I can imagine that this has to happen, because we use the keyboard communication through the ports and a keyboard interrupt could also change data on the ports. But is this true? I only guessed it...

enable_A20:
    cli

    call    a20wait
    mov     al,0xAD
    out     0x64,al

    call    a20wait
    mov     al,0xD0
    out     0x64,al

    call    a20wait2
    in      al,0x60
    push    eax

    call    a20wait
    mov     al,0xD1
    out     0x64,al

    call    a20wait
    pop     eax
    or      al,2
    out     0x60,al

    call    a20wait
    mov     al,0xAE
    out     0x64,al

    call    a20wait
    sti
    ret

a20wait:
    in      al,0x64
    test    al,2
    jnz     a20wait
    ret


a20wait2:
    in      al,0x64
    test    al,1
    jz      a20wait2
    ret

Then in the code for testing the A20 line (if it is already active), the interrupts are disabled, but never enabled. I guess not enabling them is an error? In this case, I can imagine that we have to disable interrupts, because an interrupt could jump to the memory location we modify in this piece of code and everything would break down?

check_a20:
pushf
push ds
push es
push di
push si
cli

xor ax, ax ; ax = 0
mov es, ax

not ax ; ax = 0xFFFF
mov ds, ax

mov di, 0x0500
mov si, 0x0510

mov al, byte [es:di]
push ax

mov al, byte [ds:si]
push ax

mov byte [es:di], 0x00
mov byte [ds:si], 0xFF

cmp byte [es:di], 0xFF

pop ax
mov byte [ds:si], al

pop ax
mov byte [es:di], al

mov ax, 0
je check_a20__exit

mov ax, 1

check_a20__exit:
pop si
pop di
pop es
pop ds
popf

ret

On the other hand the snippet for the fast A20 gate does not contain any interrupt disabling. But we also communicate with ports (reading and writing). So if my guess about the keyboard controller was true, couldn't it also happen that some interrupt changes the state of the 0x92 port after we read it and before we write back to it? So basically we would overwrite what the interrupt handler wanted to change.

fast_a20_gate:
in al, 0x92
test al, 2
jnz after
or al, 2
and al, 0xFE
out 0x92, al
after:

Is there any rule of thumb to easily decide when I have to cli interrupts and when not? At the moment I am totally lost in this decision and just can copy what I can see.

Upvotes: 4

Views: 474

Answers (1)

Bo Persson
Bo Persson

Reputation: 92371

When you talk to the keyboard controller you definitely want to send it the whole command as an uninterrupted sequence. So you will have to stop anyone from interrupting(!) you.

The fast_a20_gate doesn't have that problem. It is not a sequence, but just one command - a single bit actually. And if someone should happen to interfere and flip the bit, you will still set it anyway in the end.

Upvotes: 1

Related Questions