source: trunk/hal/x86_64/core/hal_acpi.c

Last change on this file was 482, checked in by viala@…, 8 years ago

[hal/x86_64] Add void type to function prototypes with no parameter

File size: 8.0 KB
Line 
1/*
2 * hal_acpi.c - ACPI parser
3 *
4 * Copyright (c) 2017 Maxime Villard
5 *
6 * This file is part of ALMOS-MKH.
7 *
8 * ALMOS-MKH is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2.0 of the License.
11 *
12 * ALMOS-MKH is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include <hal_kernel_types.h>
23#include <hal_boot.h>
24#include <hal_acpi.h>
25#include <hal_internal.h>
26
27#include <memcpy.h>
28#include <thread.h>
29#include <string.h>
30#include <process.h>
31#include <printk.h>
32#include <vmm.h>
33#include <core.h>
34#include <cluster.h>
35
36/* -------------------------------------------------------------------------- */
37
38#define RSDT_NENTRIES(rsdt) \
39 ( (rsdt->Header.Length - sizeof(rsdt_t) + sizeof(uint32_t)) / sizeof(uint32_t) )
40#define RSDT_ENTRIES(rsdt) \
41 ((uint32_t *)&rsdt->TableOffsetEntry[0])
42
43static bool_t hal_acpi_table_correct(header_t *header)
44{
45 uint8_t *ptr, sum = 0;
46 size_t i, n;
47
48 ptr = (uint8_t *)header;
49 n = header->Length;
50
51 /* Verify checksum */
52 for (i = 0; i < n; i++) {
53 sum += ptr[i];
54 }
55
56 return (sum == 0);
57}
58
59static vaddr_t hal_acpi_map_table(paddr_t headerpa, const char *sig)
60{
61 paddr_t basepa, pa;
62 vaddr_t baseva, retva, va;
63 size_t off, size;
64 size_t npages, ngrow, n;
65 header_t *header;
66
67 /* Allocate the VA for the header */
68 basepa = rounddown(headerpa, PAGE_SIZE);
69 npages = roundup(headerpa + sizeof(header_t), PAGE_SIZE) - basepa;
70 baseva = hal_gpt_bootstrap_valloc(npages);
71 off = headerpa - basepa;
72
73 /* Enter the VA, and get the total size of the structure */
74 hal_gpt_enter_range(baseva, basepa, npages);
75 retva = (vaddr_t)(baseva + off);
76 header = (header_t *)retva;
77 size = header->Length;
78 XASSERT(size >= sizeof(header_t));
79
80 /* Check the signature */
81 if (memcmp((void *)&header->Signature, sig, ACPI_NAME_SIZE))
82 return 0;
83
84 /* Grow the VA to map the rest */
85 ngrow = roundup(headerpa + size, PAGE_SIZE) - basepa;
86 n = ngrow - npages;
87 va = hal_gpt_bootstrap_valloc(n);
88 pa = basepa + npages * PAGE_SIZE;
89 hal_gpt_enter_range(va, pa, n);
90
91 /* Verify the checksum */
92 if (!hal_acpi_table_correct(header))
93 x86_panic("Wrong checksum for table");
94
95 return retva;
96}
97
98/* -------------------------------------------------------------------------- */
99
100static void hal_acpi_parse_ioapic(madt_ioapic_t *ioapic)
101{
102 extern paddr_t ioapic_pa;
103 uint32_t irqbase;
104 ioapic_pa = ioapic->Address;
105 irqbase = ioapic->GlobalIrqBase;
106
107 x86_printf("-> IOAPIC address: %Z\n", ioapic_pa);
108 x86_printf("-> IOAPIC irqbase: %z\n", (uint64_t)irqbase);
109
110 if (irqbase != 0)
111 x86_panic("irqbase != 0");
112}
113
114static void hal_acpi_parse_madt(madt_t *madt)
115{
116 madt_lapic_t *lapic;
117 madt_lapic_override_t *override;
118 void *ptr, *end;
119 subheader_t *sub;
120 size_t nioapic = 0;
121 extern size_t ncpu;
122
123 extern paddr_t lapic_pa;
124 lapic_pa = (paddr_t)madt->Address;
125
126 ptr = (void *)(madt + 1);
127 end = (void *)madt + madt->Header.Length;
128
129 while (ptr < end) {
130 sub = (subheader_t *)ptr;
131 if (sub->Type == ACPI_MADT_TYPE_IO_APIC) {
132 hal_acpi_parse_ioapic((madt_ioapic_t *)sub);
133 nioapic++;
134 } else if (sub->Type == ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE) {
135 override = (madt_lapic_override_t *)sub;
136 lapic_pa = (paddr_t)override->Address;
137 x86_printf("-> found LAPIC override\n");
138 } else if (sub->Type == ACPI_MADT_TYPE_LOCAL_APIC) {
139 lapic = (madt_lapic_t *)sub;
140 if (lapic->LapicFlags & ACPI_MADT_LAPIC_ENABLED) {
141 cpu_activate(lapic->Id);
142 x86_printf("-> found LAPIC %z\n", (uint64_t)lapic->Id);
143 ncpu++;
144 }
145 }
146
147 ptr += sub->Length;
148 }
149
150 x86_printf("-> LAPIC address: %Z\n", lapic_pa);
151 x86_printf("-> number of CPUs: %z\n", ncpu);
152 x86_printf("-> number of IOAPICs: %z\n", nioapic);
153}
154
155static madt_t *hal_acpi_map_madt(rsdt_t *rsdt)
156{
157 vaddr_t va;
158 paddr_t pa;
159 uint32_t *ent;
160 size_t i, n;
161
162 n = RSDT_NENTRIES(rsdt);
163 ent = RSDT_ENTRIES(rsdt);
164
165 for (i = 0; i < n; i++) {
166 pa = (paddr_t)ent[i];
167 va = hal_acpi_map_table(pa, "APIC");
168 if (va == 0)
169 continue;
170 return (madt_t *)va;
171 }
172
173 return NULL;
174}
175
176/* -------------------------------------------------------------------------- */
177
178static void hal_acpi_parse_srat(srat_t *srat)
179{
180 srat_cpu_affinity_t *cpu;
181 srat_mem_affinity_t *mem;
182 void *ptr, *end;
183 subheader_t *sub;
184 uint32_t dom;
185
186 ptr = (void *)(srat + 1);
187 end = (void *)srat + srat->Header.Length;
188
189 while (ptr < end) {
190 sub = (subheader_t *)ptr;
191 if (sub->Type == ACPI_SRAT_TYPE_CPU_AFFINITY) {
192 cpu = (srat_cpu_affinity_t *)sub;
193 if (cpu->Flags & ACPI_SRAT_CPU_USE_AFFINITY) {
194 dom = ((uint32_t)cpu->ProximityDomainHi[2] << 24) |
195 ((uint32_t)cpu->ProximityDomainHi[1] << 16) |
196 ((uint32_t)cpu->ProximityDomainHi[0] << 8) |
197 (uint32_t)cpu->ProximityDomainLo;
198 x86_printf("-> found CPU affinity: %z->%z\n",
199 (uint64_t)cpu->ApicId, (uint64_t)dom);
200 }
201 } else if (sub->Type == ACPI_SRAT_TYPE_MEMORY_AFFINITY) {
202 mem = (srat_mem_affinity_t *)sub;
203// if (mem->Flags & ACPI_SRAT_MEM_ENABLED)
204 x86_printf("-> found MEM affinity: %z->[%Z,%Z,%Z]\n",
205 mem->ProximityDomain,
206 mem->BaseAddress, mem->Length,(uint64_t)mem->Flags);
207 }
208
209 ptr += sub->Length;
210 }
211
212}
213
214static srat_t *hal_acpi_map_srat(rsdt_t *rsdt)
215{
216 vaddr_t va;
217 paddr_t pa;
218 uint32_t *ent;
219 size_t i, n;
220
221 n = RSDT_NENTRIES(rsdt);
222 ent = RSDT_ENTRIES(rsdt);
223
224 for (i = 0; i < n; i++) {
225 pa = (paddr_t)ent[i];
226 va = hal_acpi_map_table(pa, "SRAT");
227 if (va == 0)
228 continue;
229
230 return (srat_t *)va;
231 }
232
233 return NULL;
234}
235
236/* -------------------------------------------------------------------------- */
237
238static rsdt_t *hal_acpi_map_rsdt(rsdp_t *rsdp)
239{
240 paddr_t rsdt_pa;
241 rsdt_t *rsdt;
242
243 rsdt_pa = (paddr_t)rsdp->RsdtPhysicalAddress;
244 rsdt = (rsdt_t *)hal_acpi_map_table(rsdt_pa, "RSDT");
245 if (rsdt == 0)
246 x86_panic("RSDT invalid");
247
248 return rsdt;
249}
250
251/* -------------------------------------------------------------------------- */
252
253static bool_t hal_acpi_rsdp_correct(uint8_t *ptr)
254{
255 uint8_t sum = 0;
256 size_t i;
257
258 /* Verify checksum */
259 for (i = 0; i < 20; i++) {
260 sum += ptr[i];
261 }
262
263 return (sum == 0);
264}
265
266static rsdp_t *hal_acpi_find_rsdp(vaddr_t va_start, vaddr_t va_end)
267{
268 rsdp_t *rsdp;
269 vaddr_t va = va_start;
270 size_t i, n = PAGE_SIZE / ACPI_RSDP_ALIGN;
271 char oem[ACPI_OEM_ID_SIZE + 1];
272 uint8_t *ptr;
273
274 /* The table is on a 16bit boundary */
275 for (va = va_start; va < va_end; va += PAGE_SIZE) {
276 for (i = 0; i < n; i++) {
277 ptr = (uint8_t *)va + i * ACPI_RSDP_ALIGN;
278 if (memcmp(ptr, ACPI_RSDP_SIGNATURE, ACPI_RSDP_SIGNATURE_SIZE))
279 continue;
280 if (!hal_acpi_rsdp_correct(ptr))
281 continue;
282 goto found;
283 }
284 }
285
286 return NULL;
287
288found:
289 rsdp = (rsdp_t *)ptr;
290
291 memcpy(&oem, rsdp->OemId, ACPI_OEM_ID_SIZE);
292 oem[ACPI_OEM_ID_SIZE] = '\0';
293 x86_printf("-> OEM: %s\n", oem);
294 if (rsdp->Revision != 0)
295 x86_printf("[!] Using ACPI 1.0\n");
296
297 return rsdp;
298}
299
300/* -------------------------------------------------------------------------- */
301
302void hal_acpi_init( void )
303{
304 rsdp_t *rsdp;
305 rsdt_t *rsdt;
306 madt_t *madt;
307 srat_t *srat;
308 paddr_t bios_min = 0x0E0000;
309 paddr_t bios_max = 0x100000;
310 vaddr_t vabase;
311 size_t npages;
312
313 npages = (bios_max - bios_min) / PAGE_SIZE;
314 vabase = hal_gpt_bootstrap_valloc(npages);
315
316 hal_gpt_enter_range(vabase, bios_min, npages);
317
318 /* First, find RSDP */
319 rsdp = hal_acpi_find_rsdp(vabase, vabase + npages * PAGE_SIZE);
320 if (rsdp == NULL)
321 x86_panic("RSDP not found");
322
323 /* Then, map RSDT */
324 rsdt = hal_acpi_map_rsdt(rsdp);
325 if (rsdt == NULL)
326 x86_panic("RSDT not found");
327
328 /* Map MADT and parse it */
329 madt = hal_acpi_map_madt(rsdt);
330 if (madt == NULL)
331 x86_panic("MADT not found");
332 hal_acpi_parse_madt(madt);
333
334 /* Map SRAT and parse it */
335 srat = hal_acpi_map_srat(rsdt);
336 if (srat != NULL)
337 hal_acpi_parse_srat(srat);
338 else
339 x86_printf("-> SRAT not found, single cluster\n");
340}
341
Note: See TracBrowser for help on using the repository browser.