Skip to content

Commit 9642fc4

Browse files
authored
Merge pull request #131 from ReturnInfinity/virtio-net_int
Enable Virtio-net interrupts
2 parents e0d8b83 + 061ee7d commit 9642fc4

File tree

6 files changed

+289
-128
lines changed

6 files changed

+289
-128
lines changed

src/drivers.asm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
; Internal
1010
%include "drivers/apic.asm"
1111
%include "drivers/ioapic.asm"
12+
%include "drivers/msi.asm"
1213
%include "drivers/ps2.asm"
1314
%include "drivers/serial.asm"
1415
%include "drivers/timer.asm"

src/drivers/bus/xhci.asm

Lines changed: 7 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -27,77 +27,11 @@ xhci_init:
2727
bts eax, 1 ; Enable Memory Space
2828
call os_bus_write ; Write updated Status/Command
2929

30-
; Check for MSI-X in PCI Capabilities
31-
xhci_init_msix_check:
32-
mov dl, 1
33-
call os_bus_read ; Read register 1 for Status/Command
34-
bt eax, 20 ; Check bit 4 of the Status word (31:16)
35-
jnc xhci_init_error ; If if doesn't exist then bail out
36-
mov dl, 13
37-
call os_bus_read ; Read register 13 for the Capabilities Pointer (7:0)
38-
and al, 0xFC ; Clear the bottom two bits as they are reserved
39-
xhci_init_msix_check_cap_next:
40-
shr al, 2 ; Quick divide by 4
41-
mov dl, al
42-
call os_bus_read
43-
cmp al, 0x11
44-
je xhci_init_msix
45-
xhci_init_msix_check_cap_next_offset:
46-
shr eax, 8 ; Shift pointer to AL
47-
cmp al, 0x00 ; End of linked list?
48-
jne xhci_init_msix_check_cap_next ; If not, continue reading
49-
jmp xhci_init_msi_check ; Otherwise bail out and check for MSI
50-
xhci_init_msix:
51-
push rdx
52-
; Enable MSI-X, Mask it, Get Table Size
53-
; Example MSI-X Entry (From QEMU xHCI Controller)
54-
; 000FA011 <- Cap ID 0x11 (MSI-X), next ptr 0xA0, message control 0x000F - Table size is bits 10:0 so 0x0F
55-
; 00003000 <- BIR (2:0) is 0x0 so BAR0, Table Offset (31:3) - 8-byte aligned so clear low 3 bits - 0x3000 in this case
56-
; 00003800 <- Pending Bit BIR (2:0) and Pending Bit Offset (31:3) - 0x3800 in this case
57-
; Message Control - Enable (15), Function Mask (14), Table Size (10:0)
58-
call os_bus_read
59-
mov ecx, eax ; Save for Table Size
60-
bts eax, 31 ; Enable MSIX
61-
bts eax, 30 ; Set Function Mask
62-
call os_bus_write
63-
shr ecx, 16 ; Shift Message Control to low 16-bits
64-
and cx, 0x7FF ; Keep bits 10:0
65-
; Read the BIR and Table Offset
66-
push rdx
67-
add dl, 1
68-
call os_bus_read
69-
mov ebx, eax ; EBX for the Table Offset
70-
and ebx, 0xFFFFFFF8 ; Clear bits 2:0
71-
and eax, 0x00000007 ; Keep bits 2:0 for the BIR
72-
add al, 0x04 ; Add offset to start of BARs
73-
mov dl, al
74-
call os_bus_read ; Read the BAR address
75-
add rax, rbx ; Add offset to base
76-
sub rax, 0x04
77-
mov rdi, rax
78-
pop rdx
79-
; Configure MSI-X Table
80-
add cx, 1 ; Table Size is 0-indexed
81-
mov ebx, 0x000040A0 ; Trigger Mode (15), Level (14), Delivery Mode (10:8), Vector (7:0)
82-
xhci_init_msix_entry:
83-
mov rax, [os_LocalAPICAddress] ; 0xFEE for bits 31:20, Dest (19:12), RH (3), DM (2)
84-
stosd ; Store Message Address Low
85-
shr rax, 32 ; Rotate the high bits to EAX
86-
stosd ; Store Message Address High
87-
mov eax, ebx
88-
inc ebx
89-
stosd ; Store Message Data
90-
xor eax, eax ; Bits 31:1 are reserved, Masked (0) - 1 for masked
91-
stosd ; Store Vector Control
92-
dec cx
93-
cmp cx, 0
94-
jne xhci_init_msix_entry
95-
; Unmask MSI-X
96-
pop rdx
97-
call os_bus_read
98-
btr eax, 30 ; Clear Function Mask
99-
call os_bus_write
100-
jmp xhci_init_msix_msi_done
30+
; Configure MSI-X (if available)
31+
; TODO - Keep track of used vectors and increment as needed
32+
mov al, 0xA0
33+
call msix_init
34+
jnc xhci_init_msix_msi_done
10135

10236
; Check for MSI in PCI Capabilities
10337
xhci_init_msi_check:
@@ -347,7 +281,7 @@ xhci_reset_build_scratchpad:
347281
; ├──────────────────────────────┴───────┤
348282
; | Ring Segment Base Address Hi |
349283
; ├──────────────────┬───────────────────┤
350-
; | RsvdZ | Ring Segment Size |
284+
; | RsvdZ | Ring Segment Size |
351285
; ├──────────────────┴───────────────────┤
352286
; | RsvdZ |
353287
; └──────────────────────────────────────┘
@@ -1862,7 +1796,7 @@ xHCI_CC_STALL_ERROR equ 6
18621796
xHCI_CC_RESOURCE_ERROR equ 7
18631797
xHCI_CC_BANDWIDTH_ERROR equ 8
18641798
xHCI_CC_NO_SLOTS_ERROR equ 9
1865-
xHCI_CC_INVALID_STREAM_TYPE_ERROR equ 10
1799+
xHCI_CC_INVALID_STREAM_TYPE_ERROR equ 10
18661800
xHCI_CC_SLOT_NOT_ENABLED_ERROR equ 11
18671801
xHCI_CC_EP_NOT_ENABLED_ERROR equ 12
18681802
xHCI_CC_SHORT_PACKET equ 13

src/drivers/msi.asm

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
; =============================================================================
2+
; BareMetal -- a 64-bit OS written in Assembly for x86-64 systems
3+
; Copyright (C) 2008-2025 Return Infinity -- see LICENSE.TXT
4+
;
5+
; Message Signaled Interrupts (MSI-X and MSI)
6+
; =============================================================================
7+
8+
9+
; -----------------------------------------------------------------------------
10+
; Initialize MSI-X for a device
11+
; IN: RDX = Packed Bus address (as per syscalls/bus.asm)
12+
; AL = Start Vector
13+
; OUT: Carry flag (clear on success, set on error)
14+
; -----------------------------------------------------------------------------
15+
; Message Control - Enable (15), Function Mask (14), Table Size (10:0)
16+
;
17+
; Example MSI-X Entry (From QEMU xHCI Controller)
18+
; 000FA011 <- Cap ID 0x11 (MSI-X), next ptr 0xA0, message control 0x000F - Table size is bits 10:0 so 0x0F
19+
; 00003000 <- BIR (2:0) is 0x0 so BAR0, Table Offset (31:3) - 8-byte aligned so clear low 3 bits - 0x3000 in this case
20+
; 00003800 <- Pending Bit BIR (2:0) and Pending Bit Offset (31:3) - 0x3800 in this case
21+
;
22+
; Example MSI-X Entry (From QEMU Virtio-Net)
23+
; 00038411 <- Cap ID 0x11 (MSI-X), next ptr 0x84, message control 0x0003 - Table size is bits 10:0 so 3 (n-1 so table size is actually 4)
24+
; 00000001 <- BIR (2:0) is 0x1 so BAR1, Table Offset (31:3) - 8-byte aligned so clear low 3 bits - 0x0 in this case
25+
; 00000801 <- Pending Bit BIR (2:0) is 0x1 so BAR1 and Pending Bit Offset (31:3) is 0x800
26+
;
27+
; Resulting MSI-X table entry in memory should look similar to:
28+
; 0xXXXXXXXX: FEE00000 00000000 000040XX 00000000
29+
msix_init:
30+
push r8
31+
push rdi
32+
push rdx
33+
push rcx
34+
push rbx
35+
push rax
36+
37+
mov r8b, al
38+
39+
; Check for MSI-X in PCI Capabilities
40+
mov cl, 0x11 ; PCI Capability ID for MSI-X
41+
call os_bus_cap_check
42+
jc msix_init_error ; os_bus_cap_check sets carry flag is the cap isn't found
43+
44+
push rdx ; Save packed bus address
45+
46+
; Enable MSI-X, Mask it, Get Table Size
47+
msix_init_enable:
48+
call os_bus_read
49+
mov ecx, eax ; Save for Table Size
50+
bts eax, 31 ; Enable MSI-X
51+
bts eax, 30 ; Set Function Mask
52+
call os_bus_write
53+
shr ecx, 16 ; Shift Message Control to low 16-bits
54+
and cx, 0x7FF ; Keep bits 10:0
55+
; Read the BIR and Table Offset
56+
push rdx
57+
add dl, 1
58+
call os_bus_read
59+
mov ebx, eax ; EBX for the Table Offset
60+
and ebx, 0xFFFFFFF8 ; Clear bits 2:0
61+
and eax, 0x00000007 ; Keep bits 2:0 for the BIR
62+
63+
add al, 0x04 ; Add offset to start of BARs
64+
mov dl, al
65+
call os_bus_read ; Read the BAR address
66+
67+
; TODO - Read BAR properly
68+
; push rcx ; Save RCX as os_bus_read_bar returns a value in it
69+
; call os_bus_read_bar ; Read the BAR address
70+
; pop rcx
71+
72+
add rax, rbx ; Add offset to base
73+
and eax, 0xFFFFFFF8 ; Clear bits 2:0 of a 32-bit BAR
74+
mov rdi, rax
75+
pop rdx
76+
77+
; Configure MSI-X Table
78+
add cx, 1 ; Table Size is 0-indexed
79+
xor ebx, ebx ; Trigger Mode (15), Level (14), Delivery Mode (10:8), Vector (7:0)
80+
mov bl, r8b ; Store start vector
81+
msix_init_create_entry:
82+
mov rax, [os_LocalAPICAddress] ; 0xFEE for bits 31:20, Dest (19:12), RH (3), DM (2)
83+
stosd ; Store Message Address Low
84+
shr rax, 32 ; Rotate the high bits to EAX
85+
stosd ; Store Message Address High
86+
mov eax, ebx
87+
inc ebx
88+
stosd ; Store Message Data
89+
xor eax, eax ; Bits 31:1 are reserved, Masked (0) - 1 for masked
90+
stosd ; Store Vector Control
91+
dec cx
92+
cmp cx, 0
93+
jne msix_init_create_entry
94+
95+
; Unmask MSI-X via bus
96+
pop rdx ; Restore packed bus address
97+
call os_bus_read
98+
btr eax, 30 ; Clear Function Mask
99+
call os_bus_write
100+
101+
pop rax
102+
pop rbx
103+
pop rcx
104+
pop rdx
105+
pop rdi
106+
pop r8
107+
clc ; Clear the carry flag
108+
ret
109+
110+
msix_init_error:
111+
pop rax
112+
pop rbx
113+
pop rcx
114+
pop rdx
115+
pop rdi
116+
pop r8
117+
stc ; Set the carry flag
118+
ret
119+
; -----------------------------------------------------------------------------
120+
121+
122+
; -----------------------------------------------------------------------------
123+
; Initialize MSI for a device
124+
; IN: RDX = Packed Bus address (as per syscalls/bus.asm)
125+
; AL = Start Vector
126+
; OUT: Carry flag (clear on success, set on error)
127+
; -----------------------------------------------------------------------------
128+
; Example MSI Entry (From Intel test system)
129+
; 00869005 <- Cap ID 0x05 (MSI), next ptr 0x90, message control 0x0x0086 (64-bit, MMC 8)
130+
; 00000000 <- Message Address Low
131+
; 00000000 <- Message Address High
132+
; 00000000 <- Message Data (15:0)
133+
; 00000000 <- Mask (only exists if Per-vector masking is enabled)
134+
; 00000000 <- Pending (only exists if Per-vector masking is enabled)
135+
; Message Control - Per-vector masking (8), 64-bit (7), Multiple Message Enable (6:4), Multiple Message Capable (3:1), Enable (0)
136+
; MME/MMC 000b = 1, 001b = 2, 010b = 4, 011b = 8, 100b = 16, 101b = 32
137+
; Todo - Test bit 7, Check Multiple Message Capable, copy to Multiple Message Enable
138+
msi_init:
139+
push rdx
140+
push rcx
141+
push rbx
142+
push rax
143+
144+
mov bl, al
145+
146+
; Check for MSI in PCI Capabilities
147+
mov cl, 0x05 ; PCI Capability ID for MSI
148+
call os_bus_cap_check
149+
jc msi_init_error
150+
151+
; Enable MSI
152+
msi_init_enable:
153+
push rdx
154+
add dl, 1
155+
mov rax, [os_LocalAPICAddress] ; 0xFEE for bits 31:20, Dest (19:12), RH (3), DM (2)
156+
call os_bus_write ; Store Message Address Low
157+
add dl, 1
158+
shr rax, 32 ; Rotate the high bits to EAX
159+
call os_bus_write ; Store Message Address High
160+
add dl, 1
161+
mov eax, 0x00004000 ; Trigger Mode (15), Level (14), Delivery Mode (10:8), Vector (7:0)
162+
mov al, bl ; Store start vector
163+
call os_bus_write ; Store Message Data
164+
sub dl, 3
165+
call os_bus_read ; Get Message Control
166+
bts eax, 21 ; Debug - See MME to 8
167+
bts eax, 20 ; Debug - See MME to 8
168+
bts eax, 16 ; Set Enable
169+
call os_bus_write ; Update Message Control
170+
171+
; Unmask MSI via bus
172+
pop rdx
173+
call os_bus_read
174+
btr eax, 30 ; Clear Function Mask
175+
call os_bus_write
176+
177+
msi_init_done:
178+
pop rax
179+
pop rbx
180+
pop rcx
181+
pop rdx
182+
clc ; Clear the carry flag
183+
ret
184+
185+
msi_init_error:
186+
pop rax
187+
pop rbx
188+
pop rcx
189+
pop rdx
190+
stc ; Set the carry flag
191+
ret
192+
; -----------------------------------------------------------------------------
193+
194+
195+
; =============================================================================
196+
; EOF

0 commit comments

Comments
 (0)