MOS Source Code
Loading...
Searching...
No Matches
ioapic.c
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-3.0-or-later
2
6#include <mos/syslog/printk.h>
7#include <mos/x86/acpi/madt.h>
11
12// +-------+ +-------+ +-------+
13// | | | | | |
14// | CPU 0 | | CPU 1 | | CPU 2 | ...
15// | | | | | |
16// +-------+ +-------+ +-------+
17// | LAPIC | | LAPIC | | LAPIC | ...
18// +---+---+ +---+---+ +---+---+
19// | | |
20// | +------+ |
21// +---+ | +-----------------+
22// | | |
23// | | |
24// +--v--v--v---+
25// | I/O APIC | <- Interrupts are sent to this
26// +------------+
27
28#define IOAPIC_REG_ID 0x00
29#define IOAPIC_REG_VERSION 0x01
30#define IOAPIC_REG_ARB_ID 0x02
31#define IOAPIC_REG_REDIR_TABLE(n) (0x10 + 2 * (n))
32
33typedef struct
34{
36 u8 delivery_mode : 3; // 0 = Normal, 1 = Low Priority, 2 = SMI, 4 = NMI, 5 = INIT, 7 = External
37 bool destination_mode : 1; // 0 = Physical, 1 = Logical
38 bool pending : 1; // 1 = if this interrupt is going to be sent, but the APIC is busy
39 ioapic_polarity_t polarity : 1; // 0 = Active High, 1 = Active Low
40 bool something : 1; // 0 = a local APIC has sent an EOI, 1 = a local APIC has received the interrupt
41 ioapic_trigger_mode_t trigger_mode : 1; // 0 = Edge, 1 = Level
42 bool mask : 1; // 0 = Enabled, 1 = Disabled
44 struct
45 {
48 } __packed destination;
50
51MOS_STATIC_ASSERT(sizeof(ioapic_redirection_entry_t) == sizeof(u64), "ioapic_register_1 is not 64 bits");
52
53static u32 volatile *ioapic = NULL;
54
56{
57 ioapic[0] = reg & 0xff;
58 return ioapic[4];
59}
60
62{
63 ioapic[0] = reg & 0xff;
64 ioapic[4] = value;
65}
66
68{
69 union
70 {
71 u64 value;
73 } __packed u = { .entry = entry };
74
75 ioapic_write(IOAPIC_REG_REDIR_TABLE(irq), u.value & 0xffffffff);
76 ioapic_write(IOAPIC_REG_REDIR_TABLE(irq) + 1, u.value >> 32);
77}
78
80{
81 union
82 {
83 u64 value;
85 } __packed u = { 0 };
86
87 u.value = ioapic_read(IOAPIC_REG_REDIR_TABLE(irq));
88 u.value |= (u64) ioapic_read(IOAPIC_REG_REDIR_TABLE(irq) + 1) << 32;
89
90 return u.entry;
91}
92
93void ioapic_init(void)
94{
95 MOS_ASSERT_X(x86_ioapic_phyaddr != 0, "ioapic: no ioapic found in madt");
97 {
98 pr_info("reserving ioapic address");
100 }
101
102 ioapic = (u32 volatile *) pa_va(x86_ioapic_phyaddr);
103 const u32 ioapic_id = ioapic_read(IOAPIC_REG_ID) >> 24 & 0xf; // get the 24-27 bits
104
105 const union
106 {
107 u32 value;
108 struct
109 {
110 u32 version : 8; // 0 - 7
111 u32 reserved : 8;
112 u32 max_entries : 8; // 16 - 23
113 u32 reserved2 : 8;
114 } __packed;
115 } version = { .value = ioapic_read(IOAPIC_REG_VERSION) };
116
117 const u32 arb_id = ioapic_read(IOAPIC_REG_ARB_ID) >> 24 & 0xf; // get the 24-27 bits
118
119 pr_dinfo2(x86_ioapic, "max IRQs: %d, id: %d, version: %d, arb: %d", version.max_entries + 1, ioapic_id, version.version, arb_id);
120
121 for (int i = 0; i < version.max_entries + 1; i++)
123}
124
125void ioapic_enable_with_mode(u32 irq, u32 lapic_id, ioapic_trigger_mode_t trigger_mode, ioapic_polarity_t polarity)
126{
127 pr_dinfo2(x86_ioapic, "enable irq %d, cpu lapic-id: %d, trigger_mode %d, polarity %d", irq, lapic_id, trigger_mode, polarity);
128
129 ioapic_redirection_entry_t entry = { 0 };
130 entry.interrupt_vec = irq + ISR_MAX_COUNT; // the vector number received by the CPU
131 entry.polarity = polarity;
132 entry.trigger_mode = trigger_mode;
133 entry.destination.target_apic_id = lapic_id;
134
135 const u32 irq_overridden = x86_ioapic_get_irq_override(irq); // the irq number received by the ioapic "pin"
136 ioapic_write_redirection_entry(irq_overridden, entry);
137}
138
140{
141 ioapic_redirection_entry_t entry = { 0 };
142 entry.interrupt_vec = irq + ISR_MAX_COUNT;
143 entry.mask = true;
145}
ioapic_polarity_t
Definition apic.h:60
ioapic_trigger_mode_t
Definition apic.h:54
#define MOS_ASSERT_X(cond, msg,...)
Definition assert.h:15
#define pa_va(pa)
Definition mm.h:80
pmm_region_t * pmm_find_reserved_region(ptr_t needle)
Find a region in the physical memory manager.
Definition pmm.c:131
#define pmm_reserve_address(paddr)
Definition pmm.h:116
void ioapic_init(void)
Definition ioapic.c:93
void ioapic_enable_with_mode(u32 irq, u32 lapic_id, ioapic_trigger_mode_t trigger_mode, ioapic_polarity_t polarity)
Definition ioapic.c:125
static u32 volatile * ioapic
Definition ioapic.c:53
should_inline void ioapic_write_redirection_entry(u32 irq, ioapic_redirection_entry_t entry)
Definition ioapic.c:67
should_inline u32 ioapic_read(u32 reg)
Definition ioapic.c:55
#define IOAPIC_REG_ID
Definition ioapic.c:28
#define IOAPIC_REG_VERSION
Definition ioapic.c:29
#define IOAPIC_REG_REDIR_TABLE(n)
Definition ioapic.c:31
should_inline ioapic_redirection_entry_t ioapic_read_redirection_entry(u32 irq)
Definition ioapic.c:79
void ioapic_disable(u32 irq)
Definition ioapic.c:139
#define IOAPIC_REG_ARB_ID
Definition ioapic.c:30
should_inline void ioapic_write(u32 reg, u32 value)
Definition ioapic.c:61
u32 x86_ioapic_get_irq_override(u32 irq)
Definition madt.c:18
ptr_t x86_ioapic_phyaddr
Definition madt.c:12
#define __packed
Definition mos_global.h:29
#define should_inline
Definition mos_global.h:37
#define MOS_STATIC_ASSERT
Definition mos_global.h:14
#define NULL
Definition pb_syshdr.h:46
#define pr_info(fmt,...)
Definition printk.h:35
#define pr_dinfo2(feat, fmt,...)
Definition printk.h:27
Definition ioapic.c:34
u8 delivery_mode
Definition ioapic.c:36
struct ioapic_redirection_entry_t::@2 destination
bool pending
Definition ioapic.c:38
u8 target_apic_id
Definition ioapic.c:46
bool something
Definition ioapic.c:40
u8 interrupt_vec
Definition ioapic.c:35
u8 something_else
Definition ioapic.c:47
ioapic_trigger_mode_t trigger_mode
Definition ioapic.c:41
bool destination_mode
Definition ioapic.c:37
bool mask
Definition ioapic.c:42
ioapic_polarity_t polarity
Definition ioapic.c:39
u64 reserved
Definition ioapic.c:43
unsigned int u32
Definition types.h:21
unsigned long long u64
Definition types.h:23
unsigned char u8
Definition types.h:19
#define ISR_MAX_COUNT