another lapic/ioapic/keyboard thread
Posted: Tue Oct 04, 2016 4:10 pm
I have almost finished changing from pic to localapic/ioapic. I have some comments that might help others and some questions that I'm hoping someone can help me with. All my testing is done in virtualbox and I'm curious how relevant are the results to most systems and what are just typical virtualbox behaviour.
Based on:
But even without the above it still seems able to read my keyboard fine. I had a look and after startup, the spurious register is set to 0x10F, presumably done by the 'bios'. So the lapic is already enabled. Is this common or just a virtualbox thing?
The minimum change I needed to get the keyboard responsive again after disabling the pic, was to make the redirection entries in the IOAPIC:
The only issue I have now is that the keyboard interrupts twice for special keys (keys that prefix with an 0xE0 byte). I didn't have this problem with the pic. I would just get one interrupt, read the keyboard, if it's an E0 then read it again. But that's not working with the new setup. I mean it works but the 2nd interrupt is messing it up. How can I fix this? How can I stop 2 interrupts being generated or how can I elegantly ignore the 2nd one when the first keyboard byte is E0?
Based on:
With a uniprocessor configuration, the only lapic setup needed to get the keyboard working seems to be setting the software enable.8.4.7.1. LOCAL APIC STATE AFTER POWER-UP OR RESET
Following a power-up or RESET of the processor, the state of local APIC and its registers are
as follows:
• The following registers are reset to all 0s: the IRR, ISR, TMR, ICR, LDR, and TPR
registers; the timer initial count and timer current count registers; and the divide configuration
register.
• The DFR register is reset to all 1s.
• The LVT register entries are reset to all 0s except for the mask bits, which are set to 1s.
• The local APIC ID register is set to a unique APIC ID. (Pentium and P6 family processors
only) The Arb ID register is set to the value in the APIC ID register.
• The spurious-interrupt vector register is initialized to 0000 00FFH. The setting of bit 8 to 0
software disables the local APIC
Code: Select all
APIC_SPURIOUS = 0xF0
APIC_SW_ENABLE = 100h
mov rsi, [LocalAPICAddress]
or dword[rsi+APIC_SPURIOUS], APIC_SW_ENABLE
The minimum change I needed to get the keyboard responsive again after disabling the pic, was to make the redirection entries in the IOAPIC:
Code: Select all
set_irqs:
push r8
mov edi, [IOAPICAddress]
mov rax, 0
mov rdx, 0x20
@@:
call ioapic_set_irq
inc rdx
inc rax
cmp rax, 24
jne @b
pop r8
ret
ioapic_set_irq:
lea ebx, [0x10 + rax*2]
call ioapic_read
and ecx, 0xFFFEF0FF ; unmask the IRQ (16), set physical delivery mode (11), set fixed delivery mode (8,9,10)
mov cl, dl ; set delivery vector
call ioapic_write
lea ebx, [0x10 + rax*2 + 1]
call ioapic_read
and ecx, 0x00FFFFFF ; APICID is 0 for uniprocessor
call ioapic_write
ret
; -----------------------------------------------------------------------------
; IN : RDI = ioapic address, EBX = index register
; OUT: ECX = return value
ioapic_read:
mov [rdi], ebx
mov ecx, [rdi + 0x10]
ret
; -----------------------------------------------------------------------------
; IN : RDI = ioapic address, EBX = index register, ECX = value
; OUT: -
ioapic_write:
mov [rdi], ebx
mov [rdi + 0x10], ecx
ret