PatchworkOS  321f6ec
A non-POSIX operating system.
Loading...
Searching...
No Matches
ioapic.c
Go to the documentation of this file.
3
4#include <kernel/cpu/cpu.h>
5#include <kernel/cpu/irq.h>
6#include <kernel/log/log.h>
7#include <kernel/mem/vmm.h>
10
11#include <assert.h>
12#include <kernel/defs.h>
13
20
21static void ioapic_write(ioapic_t* ioapic, ioapic_register_t reg, uint32_t value)
22{
25 WRITE_32(base + IOAPIC_MMIO_REG_DATA, value);
26}
27
29{
30 ioapic_version_t version;
31 version.raw = ioapic_read(ioapic, IOAPIC_REG_VERSION);
32 return version;
33}
34
36{
37 assert(ioapic != NULL);
38 assert(gsi >= ioapic->globalSystemInterruptBase);
39 assert(gsi < ioapic->globalSystemInterruptBase + ioapic_version_read(ioapic).maxRedirs);
40
41 uint32_t pin = gsi - ioapic->globalSystemInterruptBase;
42 ioapic_write(ioapic, IOAPIC_REG_REDIRECTION_BASE + (pin * 2), entry.raw.low);
43 ioapic_write(ioapic, IOAPIC_REG_REDIRECTION_BASE + (pin * 2) + 1, entry.raw.high);
44}
45
47{
48 ioapic_t* ioapic = irq->domain->private;
50
51 ioapic_redirect_entry_t redirect = {
52 .vector = irq->virt,
53 .deliveryMode = IOAPIC_DELIVERY_NORMAL,
54 .destinationMode = IOAPIC_DESTINATION_PHYSICAL,
55 .deliveryStatus = 0,
57 .remoteIRR = 0,
59 .mask = 0,
60 .destination = lapic->lapicId,
61 };
62
63 ioapic_redirect_write(ioapic, irq->phys, redirect);
64 return 0;
65}
66
67static void ioapic_disable(irq_t* irq)
68{
69 ioapic_t* ioapic = irq->domain->private;
70
71 ioapic_redirect_entry_t redirect = {.mask = 1};
72
73 ioapic_redirect_write(ioapic, irq->phys, redirect);
74}
75
76static void ioapic_eoi(irq_t* irq)
77{
78 (void)irq;
79
81}
82
84 .name = "IO APIC",
85 .enable = ioapic_enable,
86 .disable = ioapic_disable,
87 .ack = NULL,
88 .eoi = ioapic_eoi,
89};
90
92{
94 if (madt == NULL)
95 {
96 LOG_ERR("no MADT table found\n");
97 return ERR;
98 }
99
100 ioapic_t* ioapic;
101 MADT_FOR_EACH(madt, ioapic)
102 {
104 {
105 continue;
106 }
107
108 void* physAddr = (void*)(uint64_t)ioapic->ioApicAddress;
109 void* virtAddr = (void*)PML_LOWER_TO_HIGHER(physAddr);
110 if (vmm_map(NULL, virtAddr, physAddr, PAGE_SIZE, PML_WRITE | PML_GLOBAL | PML_PRESENT, NULL, NULL) == NULL)
111 {
112 LOG_ERR("failed to map io apic\n");
113 return ERR;
114 }
115
116 uint32_t maxRedirs = ioapic_version_read(ioapic).maxRedirs;
117
118 LOG_INFO("found I/O APIC globalSystemInterruptBase=0x%02x maxRedirs=0x%02x\n",
119 ioapic->globalSystemInterruptBase, maxRedirs);
120
121 // Mask all interrupts.
122 for (uint32_t i = ioapic->globalSystemInterruptBase; i < ioapic->globalSystemInterruptBase + maxRedirs; i++)
123 {
124 ioapic_redirect_entry_t maskedEntry = {.mask = 1};
125 ioapic_redirect_write(ioapic, i, maskedEntry);
126 }
127
129 ioapic->globalSystemInterruptBase + maxRedirs, ioapic) == ERR)
130 {
131 LOG_ERR("failed to register io apic irq chip\n");
132 return ERR;
133 }
134 }
135
136 return 0;
137}
#define assert(expression)
Definition assert.h:29
uint64_t irq_chip_register(irq_chip_t *chip, irq_phys_t start, irq_phys_t end, void *private)
Register an IRQ chip for a range of physical IRQs.
Definition irq.c:330
@ IRQ_TRIGGER_EDGE
If set, the IRQ is edge triggered. Otherwise, level triggered.
Definition irq.h:98
@ IRQ_POLARITY_LOW
If set, the IRQ is active low. Otherwise, active high.
Definition irq.h:96
static cpuid_t cpu_get_id_unsafe(void)
Gets the current CPU ID.
Definition cpu.h:316
#define LOG_ERR(format,...)
Definition log.h:108
#define LOG_INFO(format,...)
Definition log.h:106
#define PML_LOWER_TO_HIGHER(addr)
Converts an address from the lower half to the higher half.
@ PML_PRESENT
@ PML_WRITE
@ PML_GLOBAL
void * vmm_map(space_t *space, void *virtAddr, void *physAddr, uint64_t length, pml_flags_t flags, space_callback_func_t func, void *private)
Maps physical memory to virtual memory in a given address space.
Definition vmm.c:226
#define PAGE_SIZE
The size of a memory page in bytes.
Definition proc.h:106
#define NULL
Pointer error value.
Definition NULL.h:23
#define ERR
Integer error value.
Definition ERR.h:17
sdt_header_t * acpi_tables_lookup(const char *signature, uint64_t minSize, uint64_t n)
Lookup the n'th table matching the signature.
Definition tables.c:260
#define MADT_FOR_EACH(madt, ic)
Iterate over all MADT interrupt controllers.
Definition tables.h:193
#define MADT_SIGNATURE
MADT table signature.
Definition tables.h:202
#define INTERRUPT_CONTROLLER_IO_APIC
Definition tables.h:122
ioapic_register_t
IO APIC Registers.
Definition ioapic.h:55
uint32_t ioapic_gsi_t
IO APIC Global System Interrupt type.
Definition ioapic.h:38
uint64_t ioapic_all_init(void)
Initialize all IO APICs found in the MADT.
Definition ioapic.c:91
@ IOAPIC_DELIVERY_NORMAL
Definition ioapic.h:68
@ IOAPIC_REG_VERSION
Definition ioapic.h:57
@ IOAPIC_REG_REDIRECTION_BASE
Definition ioapic.h:59
@ IOAPIC_POLARITY_LOW
Definition ioapic.h:103
@ IOAPIC_POLARITY_HIGH
Definition ioapic.h:102
@ IOAPIC_MMIO_REG_DATA
Definition ioapic.h:47
@ IOAPIC_MMIO_REG_SELECT
Definition ioapic.h:46
@ IOAPIC_TRIGGER_LEVEL
Definition ioapic.h:93
@ IOAPIC_TRIGGER_EDGE
Definition ioapic.h:92
@ IOAPIC_DESTINATION_PHYSICAL
Definition ioapic.h:82
lapic_t * lapic_get(uint32_t cpuId)
Get the lapic data for the specified CPU.
Definition lapic.c:49
void lapic_write(uint32_t reg, uint32_t value)
Write to a local apic register.
Definition lapic.c:23
@ LAPIC_REG_EOI
Definition lapic.h:55
static irq_chip_t ioApicChip
Definition ioapic.c:83
static void ioapic_disable(irq_t *irq)
Definition ioapic.c:67
static ioapic_version_t ioapic_version_read(ioapic_t *ioapic)
Definition ioapic.c:28
static void ioapic_redirect_write(ioapic_t *ioapic, ioapic_gsi_t gsi, ioapic_redirect_entry_t entry)
Definition ioapic.c:35
static void ioapic_eoi(irq_t *irq)
Definition ioapic.c:76
static uint32_t ioapic_read(ioapic_t *ioapic, ioapic_register_t reg)
Definition ioapic.c:14
static uint64_t ioapic_enable(irq_t *irq)
Definition ioapic.c:46
static void ioapic_write(ioapic_t *ioapic, ioapic_register_t reg, uint32_t value)
Definition ioapic.c:21
__UINT32_TYPE__ uint32_t
Definition stdint.h:15
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
__UINTPTR_TYPE__ uintptr_t
Definition stdint.h:43
interrupt_controller_type_t type
Definition tables.h:130
uint32_t high
Definition ioapic.h:149
uint32_t low
Definition ioapic.h:148
IO APIC.
Definition tables.h:165
uint32_t ioApicAddress
Definition tables.h:169
uint32_t globalSystemInterruptBase
Definition tables.h:170
interrupt_controller_header_t header
Definition tables.h:166
IO APIC Version Structure.
Definition ioapic.h:113
uint32_t raw
Definition ioapic.h:115
uint8_t maxRedirs
Definition ioapic.h:120
IRQ chip structure.
Definition irq.h:143
const char * name
Definition irq.h:144
void * private
Definition irq.h:131
IRQ structure.
Definition irq.h:110
irq_virt_t virt
Definition irq.h:112
irq_domain_t * domain
Definition irq.h:115
irq_phys_t phys
Definition irq.h:111
irq_flags_t flags
Definition irq.h:113
Local APIC Structure.
Definition lapic.h:123
lapic_id_t lapicId
Definition lapic.h:125
Multiple APIC Description Table.
Definition tables.h:180
IO APIC Redirection Entry Structure.
Definition ioapic.h:132
struct ioapic_redirect_entry_t::PACKED raw
#define WRITE_32(address, value)
Definition utils.h:16
#define READ_32(address)
Definition utils.h:15