-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathacpi.c
106 lines (95 loc) · 2.96 KB
/
acpi.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include <kernel.h>
volatile struct limine_rsdp_request rsdp_request = {
.id = LIMINE_RSDP_REQUEST,
.revision = 0,
};
static uint8_t lapic_ids[256] = { 0 }; // CPU core Local APIC IDs
static uint8_t ioapic_ids[256] = { 0 }; // CPU core Local APIC IDs
static uint16_t numcore = 0; // number of cores detected
static uint16_t numioapic = 0;
static uint64_t lapic_ptr = 0; // pointer to the Local APIC MMIO registers
static uint64_t ioapic_ptr[256] = { 0 }; // pointer to the IO APIC MMIO registers
static uint32_t ioapic_gsi_base[256] = { 0 };
static uint8_t ioapic_gsi_count[256] = { 0 };
rsdp_t* get_rsdp() {
return (rsdp_t*) rsdp_request.response->address;
}
sdt_header_t* get_sdt_header() {
rsdp_t* rsdp = get_rsdp();
return (sdt_header_t*) (uint64_t) rsdp->rsdt_address;
}
uint8_t* get_lapic_ids()
{
return lapic_ids;
}
uint16_t get_cpu_count()
{
return numcore;
}
uint64_t get_local_apic()
{
return (uint64_t) lapic_ptr;
}
uint16_t get_ioapic_count()
{
return numioapic;
}
ioapic_t get_ioapic(uint16_t index)
{
ioapic_t ioapic = { 0 };
if (index >= numioapic) {
return ioapic;
}
ioapic.gsi_base = ioapic_gsi_base[index];
ioapic.gsi_count = ioapic_gsi_count[index];
ioapic.id = ioapic_ids[index];
ioapic.paddr = ioapic_ptr[index];
return ioapic;
}
void init_cores()
{
uint8_t *ptr, *ptr2;
uint32_t len;
uint8_t* rsdt = (uint8_t*)get_sdt_header();
numcore = 0;
numioapic = 0;
// Iterate on ACPI table pointers
for (len = *((uint32_t*)(rsdt + 4)), ptr2 = rsdt + 36; ptr2 < rsdt + len; ptr2 += rsdt[0]=='X' ? 8 : 4) {
ptr = (uint8_t*)(uint64_t)(rsdt[0]=='X' ? *((uint64_t*)ptr2) : *((uint32_t*)ptr2));
if (*ptr == 'A' && *(ptr + 1) == 'P' && *(ptr + 2) == 'I' && *(ptr + 3) == 'C') {
// found MADT
lapic_ptr = (uint64_t)(*((uint32_t*)(ptr + 0x24)));
kprintf("Detected: 32-Bit Local APIC [base: %llx]\n", lapic_ptr);
ptr2 = ptr + *((uint32_t*)(ptr + 4));
// iterate on variable length records
for (ptr += 44; ptr < ptr2; ptr += ptr[1]) {
switch (ptr[0]) {
case 0:
if (ptr[4] & 1) {
lapic_ids[numcore++] = ptr[3];
}
break; // found Processor Local APIC
case 1:
ioapic_ptr[numioapic] = (uint64_t)*((uint32_t*)(ptr + 4));
ioapic_ids[numioapic] = ptr[2];
ioapic_gsi_base[numioapic] = (uint32_t)*((uint32_t*)(ptr + 8));
uint32_t *mmio = (uint32_t*)ioapic_ptr[numioapic];
mmio[0] = 0x01;
uint32_t count = ((mmio[0x10 / 4]) & 0xFF) + 1;
ioapic_gsi_count[numioapic] = count;
kprintf("Detected: IOAPIC [base: %llx; id: %d gsi base: %d gsi count: %d]\n", ioapic_ptr[numioapic], ioapic_ids[numioapic], ioapic_gsi_base[numioapic], count);
numioapic++;
break; // found IOAPIC
case 5:
lapic_ptr = *((uint64_t*)(ptr + 4));
kprintf("Detected: 64-Bit Local APIC [base: %llx]\n", lapic_ptr);
break; // found 64 bit LAPIC
}
}
break;
}
}
if (numcore > 0) {
kprintf("SMP: %d cores, %d IOAPICs\n", numcore, numioapic);
}
}