kernel: Support more than one I/O APIC and 24 interrupts.

git-svn-id: svn://kolibrios.org@7733 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Ivan Baravy 2020-03-02 04:25:30 +00:00
parent 57b2e6af66
commit cbceb320e8
5 changed files with 154 additions and 70 deletions

View File

@ -1,20 +1,21 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;; ;; ;;
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;; ;; Copyright (C) KolibriOS team 2004-2020. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;; ;; Distributed under terms of the GNU General Public License ;;
;; ;; ;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
$Revision$ $Revision$
MAX_IOAPICS = 2
iglobal
IRQ_COUNT dd 24
endg
uglobal uglobal
irq_mode rd 1 IRQ_COUNT rd MAX_IOAPICS
IOAPIC_base rd 1 irq_mode rd 1 ; PIC/(IO)APIC
IOAPIC_base rd MAX_IOAPICS
ioapic_gsi_base rd MAX_IOAPICS ; zero-based, i.e. not vector
ioapic_cnt dd ? ; from MADT aka APIC table
ioapic_cur dd ?
LAPIC_BASE rd 1 LAPIC_BASE rd 1
endg endg
@ -45,6 +46,7 @@ IOAPIC_REDTBL = 0x10
align 4 align 4
APIC_init: APIC_init:
push ebx
mov [irq_mode], IRQ_PIC mov [irq_mode], IRQ_PIC
cmp [acpi_ioapic_base], 0 cmp [acpi_ioapic_base], 0
@ -60,39 +62,51 @@ APIC_init:
mov [acpi_dev_data], eax mov [acpi_dev_data], eax
mov [acpi_dev_size], ebx mov [acpi_dev_size], ebx
call IRQ_mask_all
; IOAPIC init ; IOAPIC init
stdcall map_io_mem, [acpi_ioapic_base], 0x20, PG_GLOBAL+PG_NOCACHE+PG_SWR xor ebx, ebx
mov [IOAPIC_base], eax @@:
stdcall map_io_mem, [acpi_ioapic_base+ebx*4], 0x20, PG_GLOBAL+PG_NOCACHE+PG_SWR
mov [IOAPIC_base+ebx*4], eax
inc ebx
cmp ebx, [ioapic_cnt]
jnz @b
call IRQ_mask_all
mov [ioapic_cur], 0
.next_ioapic:
mov edx, [ioapic_cur]
mov eax, IOAPIC_VER mov eax, IOAPIC_VER
call IOAPIC_read call IOAPIC_read
shr eax, 16 shr eax, 16
inc al inc al
movzx eax, al movzx eax, al
cmp al, IRQ_RESERVED mov ecx, [ioapic_gsi_base+edx*4]
cmp ecx, IRQ_RESERVED
jae .lapic_init
add ecx, eax
sub ecx, IRQ_RESERVED
jbe @f jbe @f
sub eax, ecx
mov al, IRQ_RESERVED
@@: @@:
mov [IRQ_COUNT], eax mov [IRQ_COUNT+edx*4], eax
; Reroute IOAPIC & mask all interrupts ; Reroute IOAPIC & mask all interrupts
xor ecx, ecx xor ecx, ecx
mov eax, IOAPIC_REDTBL mov eax, IOAPIC_REDTBL
@@: .next_irq:
mov ebx, eax mov ebx, eax
call IOAPIC_read call IOAPIC_read
mov ah, 0x08; Delivery Mode: Fixed, Destination Mode: Logical mov ah, 0x08; Delivery Mode: Fixed, Destination Mode: Logical
mov al, cl mov al, cl
add al, 0x20; vector add al, 0x20; vector
or eax, 0x10000; Mask Interrupt add eax, [ioapic_gsi_base+edx*4]
or eax, 0x1a000; Mask Interrupt, level-triggered active-low
cmp [ioapic_cur], 0
jnz @f
cmp ecx, 16 cmp ecx, 16
jb .set jae @f
and eax, NOT 0xa000 ; edge-triggered active-high for IRQ0-15
or eax, 0xa000;<<< level-triggered active-low for IRQ16+ @@:
.set:
xchg eax, ebx xchg eax, ebx
call IOAPIC_write call IOAPIC_write
inc eax inc eax
@ -103,9 +117,15 @@ APIC_init:
call IOAPIC_write call IOAPIC_write
inc eax inc eax
inc ecx inc ecx
cmp ecx, [IRQ_COUNT] cmp ecx, [IRQ_COUNT+edx*4]
jb @b jb .next_irq
inc [ioapic_cur]
inc edx
cmp edx, [ioapic_cnt]
jnz .next_ioapic
.lapic_init:
call LAPIC_init call LAPIC_init
mov [irq_mode], IRQ_APIC mov [irq_mode], IRQ_APIC
@ -117,7 +137,7 @@ APIC_init:
call pci_irq_fixup call pci_irq_fixup
.no_apic: .no_apic:
pop ebx
ret ret
;=========================================================== ;===========================================================
@ -210,7 +230,8 @@ IOAPIC_read:
; in : EAX - IOAPIC register ; in : EAX - IOAPIC register
; out: EAX - readed value ; out: EAX - readed value
push esi push esi
mov esi, [IOAPIC_base] mov esi, [ioapic_cur]
mov esi, [IOAPIC_base+esi*4]
mov [esi], eax mov [esi], eax
mov eax, [esi + 0x10] mov eax, [esi + 0x10]
pop esi pop esi
@ -222,7 +243,8 @@ IOAPIC_write:
; EBX - value ; EBX - value
; out: none ; out: none
push esi push esi
mov esi, [IOAPIC_base] mov esi, [ioapic_cur]
mov esi, [IOAPIC_base+esi*4]
mov [esi], eax mov [esi], eax
mov [esi + 0x10], ebx mov [esi + 0x10], ebx
pop esi pop esi
@ -232,6 +254,7 @@ IOAPIC_write:
; IRQ0 to vector 0x20, IRQ1 to vector 0x21.... ; IRQ0 to vector 0x20, IRQ1 to vector 0x21....
align 4 align 4
PIC_init: PIC_init:
mov [IRQ_COUNT], 16
cli cli
mov al, 0x11 ; icw4, edge triggered mov al, 0x11 ; icw4, edge triggered
out 0x20, al out 0x20, al
@ -252,7 +275,6 @@ PIC_init:
out 0xA1, al out 0xA1, al
call IRQ_mask_all call IRQ_mask_all
; mov dword[irq_type_to_set], IRQ_TYPE_PIC
ret ret
; ----------------------------------------- ; -----------------------------------------
@ -309,7 +331,12 @@ IRQ_mask_all:
mov ecx, 0x1000 mov ecx, 0x1000
ret ret
.APIC: .APIC:
mov ecx, [IRQ_COUNT] cmp [IOAPIC_base], 0
jz .done
mov [ioapic_cur], 0
.next_ioapic:
mov edx, [ioapic_cur]
mov ecx, [IRQ_COUNT+edx*4]
mov eax, 0x10 mov eax, 0x10
@@: @@:
mov ebx, eax mov ebx, eax
@ -320,6 +347,12 @@ IRQ_mask_all:
inc eax inc eax
inc eax inc eax
loop @b loop @b
inc [ioapic_cur]
inc edx
cmp edx, [ioapic_cnt]
jnz .next_ioapic
.done:
ret ret
; ----------------------------------------- ; -----------------------------------------
@ -363,6 +396,20 @@ proc enable_irq stdcall, irq_line:dword
out dx, al out dx, al
ret ret
.APIC: .APIC:
push [ioapic_cur]
xor eax, eax
.next_ioapic:
mov ecx, [ioapic_gsi_base+eax*4]
add ecx, [IRQ_COUNT+eax*4]
cmp ebx, ecx
jb .found
inc eax
cmp eax, [ioapic_cnt]
jnz .next_ioapic
jmp .done
.found:
mov [ioapic_cur], eax
sub ebx, [ioapic_gsi_base+eax*4]
shl ebx, 1 shl ebx, 1
add ebx, 0x10 add ebx, 0x10
mov eax, ebx mov eax, ebx
@ -370,6 +417,8 @@ proc enable_irq stdcall, irq_line:dword
and eax, 0xfffeffff; bit 16 and eax, 0xfffeffff; bit 16
xchg eax, ebx xchg eax, ebx
call IOAPIC_write call IOAPIC_write
.done:
pop [ioapic_cur]
ret ret
endp endp
@ -390,6 +439,20 @@ proc disable_irq stdcall, irq_line:dword
out dx, al out dx, al
ret ret
.APIC: .APIC:
push [ioapic_cur]
xor eax, eax
.next_ioapic:
mov ecx, [ioapic_gsi_base+eax*4]
add ecx, [IRQ_COUNT+eax*4]
cmp ebx, ecx
jae .found
inc eax
cmp eax, [ioapic_cnt]
jnz .next_ioapic
jmp .done
.found:
mov [ioapic_cur], eax
sub ebx, [ioapic_gsi_base+eax*4]
shl ebx, 1 shl ebx, 1
add ebx, 0x10 add ebx, 0x10
mov eax, ebx mov eax, ebx
@ -397,6 +460,8 @@ proc disable_irq stdcall, irq_line:dword
or eax, 0x10000; bit 16 or eax, 0x10000; bit 16
xchg eax, ebx xchg eax, ebx
call IOAPIC_write call IOAPIC_write
.done:
pop [ioapic_cur]
ret ret
endp endp

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;; ;; ;;
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;; ;; Copyright (C) KolibriOS team 2004-2020. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;; ;; Distributed under terms of the GNU General Public License ;;
;; ;; ;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -8,7 +8,7 @@
$Revision$ $Revision$
IRQ_RESERVED = 24 IRQ_RESERVED = 56
IRQ_POOL_SIZE = 48 IRQ_POOL_SIZE = 48
@ -20,11 +20,27 @@ irqh_tab rd sizeof.LHEAD * IRQ_RESERVED / 4
irqh_pool rd sizeof.IRQH * IRQ_POOL_SIZE /4 irqh_pool rd sizeof.IRQH * IRQ_POOL_SIZE /4
next_irqh rd 1 next_irqh rd 1
irq_active_set rd 1 irq_active_set rd (IRQ_RESERVED+31)/32
irq_failed rd IRQ_RESERVED irq_failed rd IRQ_RESERVED
endg endg
set_irq_active:
mov eax, ebp
mov ecx, ebp
shr ecx, 5
and eax, 31
bts [irq_active_set+ecx*4], eax
ret
reset_irq_active:
mov eax, ebp
mov ecx, ebp
shr ecx, 5
and eax, 31
btr [irq_active_set+ecx*4], eax
ret
align 4 align 4
init_irqs: init_irqs:
@ -137,20 +153,15 @@ align 4
align 16 align 16
irq_serv: irq_serv:
; .irq_1: rept 12 irqn:1 {irq_serv_h irqn} ; 1--12
; push 1 rept 18 irqn:14 {irq_serv_h irqn} ; 14--31 (irq32 is vector 0x40)
; jmp .main rept 23 irqn:33 {irq_serv_h irqn} ; 33--55
; etc...
irq_serv_h 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15
irq_serv_h 16, 17, 18, 19, 20, 21, 22, 23
purge irq_serv_h purge irq_serv_h
align 16 align 16
.main: .main:
save_ring3_context save_ring3_context
mov ebp, [esp + 32] mov ebp, [esp + 32]
mov bx, app_data;os_data mov bx, app_data;os_data
mov ds, bx mov ds, bx
@ -159,7 +170,7 @@ align 16
cmp [v86_irqhooks+ebp*8], 0 cmp [v86_irqhooks+ebp*8], 0
jnz v86_irq jnz v86_irq
bts [irq_active_set], ebp call set_irq_active
lea esi, [irqh_tab+ebp*8] ; esi= list head lea esi, [irqh_tab+ebp*8] ; esi= list head
mov ebx, esi mov ebx, esi
@ -184,11 +195,11 @@ align 16
jz .next jz .next
inc [ebx+IRQH.num_ints] inc [ebx+IRQH.num_ints]
btr [irq_active_set], ebp call reset_irq_active
jmp .next jmp .next
.done: .done:
btr [irq_active_set], ebp call reset_irq_active
jnc .exit jnc .exit
; There is at least one configuration with one device which generates IRQ ; There is at least one configuration with one device which generates IRQ

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;; ;; ;;
;; Copyright (C) KolibriOS team 2004-2016. All rights reserved. ;; ;; Copyright (C) KolibriOS team 2004-2020. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License. ;; ;; Distributed under terms of the GNU General Public License. ;;
;; ;; ;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -20,6 +20,13 @@ build_interrupt_table:
loop @b loop @b
movsd ;copy low dword of trap gate for int 0x40 movsd ;copy low dword of trap gate for int 0x40
movsd ;copy high dword of trap gate for int 0x40 movsd ;copy high dword of trap gate for int 0x40
mov ecx, 23
mov eax, (10001110b shl 24) + os_code
@@:
movsw ;low word of code-entry
stosd ;interrupt gate type : os_code selector
movsw ;high word of code-entry
loop @b
lidt [esi] lidt [esi]
ret ret
@ -33,29 +40,21 @@ iglobal
times 12 dd unknown_interrupt ;int_20..int_31 times 12 dd unknown_interrupt ;int_20..int_31
;interrupt handlers addresses (for interrupt gate construction) ;interrupt handlers addresses (for interrupt gate construction)
; 0x20 .. 0x2F - IRQ handlers ; 0x20+ are IRQ handlers
dd irq0, irq_serv.irq_1, irq_serv.irq_2 dd irq0
dd irq_serv.irq_3, irq_serv.irq_4 rept 12 irqn:1 \{dd irq_serv.irq_\#irqn\}
dd irq_serv.irq_5, irq_serv.irq_6, irq_serv.irq_7 dd irqD
dd irq_serv.irq_8, irq_serv.irq_9, irq_serv.irq_10 rept 18 irqn:14 \{dd irq_serv.irq_\#irqn\}
dd irq_serv.irq_11, irq_serv.irq_12, irqD, irq_serv.irq_14, irq_serv.irq_15
dd irq_serv.irq_16
dd irq_serv.irq_17
dd irq_serv.irq_18
dd irq_serv.irq_19
dd irq_serv.irq_20
dd irq_serv.irq_21
dd irq_serv.irq_22
dd irq_serv.irq_23
times 32 - IRQ_RESERVED dd unknown_interrupt ; int_0x40 gate trap (for directly copied)
;int_0x40 gate trap (for directly copied) dw i40 and 0xFFFF, os_code, 11101111b shl 8, i40 shr 16
dw i40 and 0xFFFF, os_code, 11101111b shl 8, i40 shr 16
rept 23 irqn:33 \{dd irq_serv.irq_\#irqn\}
idtreg: ; data for LIDT instruction (!!! must be immediately below sys_int data) idtreg: ; data for LIDT instruction (!!! must be immediately below sys_int data)
dw 2*($-sys_int-4)-1 dw 2*($-sys_int-4)-1
dd idts ;0x8000B100 dd idts ;0x8000B100
dw 0 ;просто выравнивание dw 0 ;alignment
msg_fault_sel dd msg_exc_8,msg_exc_u,msg_exc_a,msg_exc_b msg_fault_sel dd msg_exc_8,msg_exc_u,msg_exc_a,msg_exc_b
dd msg_exc_c,msg_exc_d,msg_exc_e,msg_exc_u dd msg_exc_c,msg_exc_d,msg_exc_e,msg_exc_u

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;; ;; ;;
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;; ;; Copyright (C) KolibriOS team 2004-2020. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;; ;; Distributed under terms of the GNU General Public License ;;
;; ;; ;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -429,7 +429,7 @@ acpi_fadt_base rd 1
acpi_dsdt_base rd 1 acpi_dsdt_base rd 1
acpi_dsdt_size rd 1 acpi_dsdt_size rd 1
acpi_madt_base rd 1 acpi_madt_base rd 1
acpi_ioapic_base rd 1 acpi_ioapic_base rd MAX_IOAPICS
acpi_hpet_base rd 1 acpi_hpet_base rd 1
hpet_base rd 1 hpet_base rd 1
hpet_period rd 1 hpet_period rd 1
@ -581,14 +581,18 @@ check_acpi:
inc [cpu_count-OS_BASE] inc [cpu_count-OS_BASE]
add edi, 4 add edi, 4
mov [ioapic_cnt-OS_BASE], 0
lea edx, [eax+44] lea edx, [eax+44]
mov ecx, [eax+4] mov ecx, [eax+4]
add ecx, eax add ecx, eax
.check: .check:
mov eax, [edx] mov eax, [edx]
cmp al, 0 cmp al, 0
jne .io_apic je .lapic
cmp al, 1
je .io_apic
jmp .next
.lapic:
shr eax, 24 ; get APIC ID shr eax, 24 ; get APIC ID
cmp eax, ebx ; skip self cmp eax, ebx ; skip self
je .next je .next
@ -611,11 +615,12 @@ check_acpi:
ret ret
.io_apic: .io_apic:
cmp al, 1 mov eax, [ioapic_cnt-OS_BASE]
jne .next push dword[edx+4]
pop [acpi_ioapic_base-OS_BASE+eax*4]
mov eax, [edx+4] push dword[edx+8]
mov [acpi_ioapic_base-OS_BASE], eax pop [ioapic_gsi_base-OS_BASE+eax*4]
inc [ioapic_cnt-OS_BASE]
jmp .next jmp .next
HPET_PERIOD = 0x0004 HPET_PERIOD = 0x0004

View File

@ -715,7 +715,11 @@ endg
; Enable timer IRQ (IRQ0) and co-processor IRQ (IRQ13) ; Enable timer IRQ (IRQ0) and co-processor IRQ (IRQ13)
; they are used: when partitions are scanned, hd_read relies on timer ; they are used: when partitions are scanned, hd_read relies on timer
call unmask_timer call unmask_timer
; Prevent duplicate timer IRQs in APIC mode
cmp [irq_mode], IRQ_APIC
jz @f
stdcall enable_irq, 2 ; @#$%! PIC stdcall enable_irq, 2 ; @#$%! PIC
@@:
stdcall enable_irq, 13 ; co-processor stdcall enable_irq, 13 ; co-processor
; Setup serial output console (if enabled) ; Setup serial output console (if enabled)