1/* 2 * Copyright 2014, General Dynamics C4 Systems 3 * 4 * SPDX-License-Identifier: GPL-2.0-only 5 */ 6 7#include <config.h> 8#include <util.h> 9#include <assert.h> 10#include <machine/io.h> 11#include <linker.h> 12#include <plat/machine.h> 13#include <plat/machine/acpi.h> 14#include <plat/machine/devices.h> 15 16enum acpi_type { 17 ACPI_RSDP, 18 ACPI_RSDT 19}; 20 21/* DMA Remapping Reporting Table */ 22typedef struct acpi_dmar { 23 acpi_header_t header; 24 uint8_t host_addr_width; 25 uint8_t flags; 26 uint8_t reserved[10]; 27} acpi_dmar_t; 28compile_assert(acpi_dmar_packed, 29 sizeof(acpi_dmar_t) == sizeof(acpi_header_t) + 12) 30 31/* DMA Remapping Structure Header */ 32typedef struct acpi_dmar_header { 33 uint16_t type; 34 uint16_t length; 35} acpi_dmar_header_t; 36compile_assert(acpi_dmar_header_packed, sizeof(acpi_dmar_header_t) == 4) 37 38/* DMA Remapping Structure Types */ 39enum acpi_table_dmar_struct_type { 40 DMAR_DRHD = 0, 41 DMAR_RMRR = 1, 42 DMAR_ATSR = 2, 43}; 44 45/* DMA Remapping Hardware unit Definition */ 46typedef struct acpi_dmar_drhd { 47 acpi_dmar_header_t header; 48 uint8_t flags; 49 uint8_t reserved; 50 uint16_t segment; 51 uint32_t reg_base[2]; 52} acpi_dmar_drhd_t; 53compile_assert(acpi_dmar_drhd_packed, 54 sizeof(acpi_dmar_drhd_t) == sizeof(acpi_dmar_header_t) + 12) 55 56/* Reserved Memory Region Reporting structure Definition */ 57typedef struct acpi_dmar_devscope { 58 uint8_t type; 59 uint8_t length; 60 uint16_t reserved; 61 uint8_t enum_id; 62 uint8_t start_bus; 63 struct { 64 uint8_t dev; 65 uint8_t fun; 66 } path_0; 67} acpi_dmar_devscope_t; 68compile_assert(acpi_dmar_devscope_packed, sizeof(acpi_dmar_devscope_t) == 8) 69 70/* Reserved Memory Region Reporting structure Definition */ 71typedef struct acpi_dmar_rmrr { 72 acpi_dmar_header_t header; 73 uint16_t reserved; 74 uint16_t segment; 75 uint32_t reg_base[2]; 76 uint32_t reg_limit[2]; 77 acpi_dmar_devscope_t devscope_0; 78} acpi_dmar_rmrr_t; 79compile_assert(acpi_dmar_rmrr_packed, sizeof(acpi_dmar_rmrr_t) == 80 sizeof(acpi_dmar_header_t) + 20 + sizeof(acpi_dmar_devscope_t)) 81 82/* Fixed ACPI Description Table (FADT), partial as we only need flags */ 83typedef struct acpi_fadt { 84 acpi_header_t header; 85 uint8_t reserved[76]; 86 uint32_t flags; 87} acpi_fadt_t; 88compile_assert(acpi_fadt_packed, 89 sizeof(acpi_fadt_t) == sizeof(acpi_header_t) + 80) 90 91/* Multiple APIC Description Table (MADT) */ 92typedef struct acpi_madt { 93 acpi_header_t header; 94 uint32_t apic_addr; 95 uint32_t flags; 96} acpi_madt_t; 97compile_assert(acpi_madt_packed, 98 sizeof(acpi_madt_t) == sizeof(acpi_header_t) + 8) 99 100typedef struct acpi_madt_header { 101 uint8_t type; 102 uint8_t length; 103} acpi_madt_header_t; 104compile_assert(acpi_madt_header_packed, sizeof(acpi_madt_header_t) == 2) 105 106enum acpi_table_madt_struct_type { 107 MADT_APIC = 0, 108 MADT_IOAPIC = 1, 109 MADT_ISO = 2, 110 MADT_x2APIC = 9 111}; 112 113typedef struct acpi_madt_apic { 114 acpi_madt_header_t header; 115 uint8_t cpu_id; 116 uint8_t apic_id; 117 uint32_t flags; 118} acpi_madt_apic_t; 119compile_assert(acpi_madt_apic_packed, 120 sizeof(acpi_madt_apic_t) == sizeof(acpi_madt_header_t) + 6) 121 122typedef struct acpi_madt_x2apic { 123 acpi_madt_header_t header; 124 uint16_t reserved; 125 uint32_t x2apic_id; 126 uint32_t flags; 127 uint32_t acpi_processor_uid; 128} acpi_madt_x2apic_t; 129compile_assert(acpi_madt_x2apic_packed, 130 sizeof(acpi_madt_x2apic_t) == sizeof(acpi_madt_header_t) + 14) 131 132typedef struct acpi_madt_ioapic { 133 acpi_madt_header_t header; 134 uint8_t ioapic_id; 135 uint8_t reserved[1]; 136 uint32_t ioapic_addr; 137 uint32_t gsib; 138} acpi_madt_ioapic_t; 139compile_assert(acpi_madt_ioapic_packed, 140 sizeof(acpi_madt_ioapic_t) == sizeof(acpi_madt_header_t) + 10) 141 142typedef struct acpi_madt_iso { 143 acpi_madt_header_t header; 144 uint8_t bus; /* always 0 (ISA) */ 145 uint8_t source; 146 uint32_t gsi; 147 uint16_t flags; 148} acpi_madt_iso_t; 149/* We can't assert on the sizeof acpi_madt_iso because it contains trailing 150 * padding. 151 */ 152unverified_compile_assert(acpi_madt_iso_packed, 153 OFFSETOF(acpi_madt_iso_t, flags) == sizeof(acpi_madt_header_t) + 6) 154 155/* workaround because string literals are not supported by C parser */ 156const char acpi_str_rsd[] = {'R', 'S', 'D', ' ', 'P', 'T', 'R', ' ', 0}; 157const char acpi_str_fadt[] = {'F', 'A', 'C', 'P', 0}; 158const char acpi_str_apic[] = {'A', 'P', 'I', 'C', 0}; 159const char acpi_str_dmar[] = {'D', 'M', 'A', 'R', 0}; 160 161BOOT_CODE static uint8_t acpi_calc_checksum(char *start, uint32_t length) 162{ 163 uint8_t checksum = 0; 164 165 while (length > 0) { 166 checksum += *start; 167 start++; 168 length--; 169 } 170 return checksum; 171} 172 173BOOT_CODE static acpi_rsdp_t *acpi_get_rsdp(void) 174{ 175 char *addr; 176 177 for (addr = (char *)BIOS_PADDR_START; addr < (char *)BIOS_PADDR_END; addr += 16) { 178 if (strncmp(addr, acpi_str_rsd, 8) == 0) { 179 if (acpi_calc_checksum(addr, ACPI_V1_SIZE) == 0) { 180 return (acpi_rsdp_t *)addr; 181 } 182 } 183 } 184 return NULL; 185} 186 187BOOT_CODE static void *acpi_table_init(void *entry, enum acpi_type table_type) 188{ 189 void *acpi_table; 190 unsigned int pages_for_table; 191 unsigned int pages_for_header = 1; 192 193 /* if we need to map another page to read header */ 194 unsigned long offset_in_page = (unsigned long)entry & MASK(LARGE_PAGE_BITS); 195 if (MASK(LARGE_PAGE_BITS) - offset_in_page < sizeof(acpi_rsdp_t)) { 196 pages_for_header++; 197 } 198 199 /* map in table's header */ 200 acpi_table = map_temp_boot_page(entry, pages_for_header); 201 202 switch (table_type) { 203 case ACPI_RSDP: { 204 acpi_rsdp_t *rsdp_entry = (acpi_rsdp_t *)entry; 205 pages_for_table = (rsdp_entry->length + offset_in_page) / MASK(LARGE_PAGE_BITS) + 1; 206 break; 207 } 208 case ACPI_RSDT: { // RSDT, MADT, DMAR etc. 209 acpi_rsdt_t *rsdt_entry = (acpi_rsdt_t *)entry; 210 pages_for_table = (rsdt_entry->header.length + offset_in_page) / MASK(LARGE_PAGE_BITS) + 1; 211 break; 212 } 213 default: 214 printf("Error: Mapping unknown ACPI table type\n"); 215 assert(false); 216 return NULL; 217 } 218 219 /* map in full table */ 220 acpi_table = map_temp_boot_page(entry, pages_for_table); 221 222 return acpi_table; 223} 224 225BOOT_CODE bool_t acpi_init(acpi_rsdp_t *rsdp_data) 226{ 227 acpi_rsdp_t *acpi_rsdp = acpi_get_rsdp(); 228 229 if (acpi_rsdp == NULL) { 230 printf("BIOS: No ACPI support detected\n"); 231 return false; 232 } 233 printf("ACPI: RSDP paddr=%p\n", acpi_rsdp); 234 acpi_rsdp = acpi_table_init(acpi_rsdp, ACPI_RSDP); 235 printf("ACPI: RSDP vaddr=%p\n", acpi_rsdp); 236 237 /* create a copy of the rsdp data */ 238 *rsdp_data = *acpi_rsdp; 239 240 /* perform final validation */ 241 return acpi_validate_rsdp(rsdp_data); 242} 243 244BOOT_CODE bool_t acpi_validate_rsdp(acpi_rsdp_t *acpi_rsdp) 245{ 246 acpi_rsdt_t *acpi_rsdt; 247 acpi_rsdt_t *acpi_rsdt_mapped; 248 249 if (acpi_calc_checksum((char *)acpi_rsdp, ACPI_V1_SIZE) != 0) { 250 printf("BIOS: ACPIv1 information corrupt\n"); 251 return false; 252 } 253 254 if (acpi_rsdp->revision > 0 && acpi_calc_checksum((char *)acpi_rsdp, sizeof(*acpi_rsdp)) != 0) { 255 printf("BIOS: ACPIv2 information corrupt\n"); 256 return false; 257 } 258 259 /* verify the rsdt, even though we do not actually make use of the mapping right now */ 260 acpi_rsdt = (acpi_rsdt_t *)(word_t)acpi_rsdp->rsdt_address; 261 printf("ACPI: RSDT paddr=%p\n", acpi_rsdt); 262 acpi_rsdt_mapped = (acpi_rsdt_t *)acpi_table_init(acpi_rsdt, ACPI_RSDT); 263 printf("ACPI: RSDT vaddr=%p\n", acpi_rsdt_mapped); 264 265 assert(acpi_rsdt_mapped->header.length > 0); 266 if (acpi_calc_checksum((char *)acpi_rsdt_mapped, acpi_rsdt_mapped->header.length) != 0) { 267 printf("ACPI: RSDT checksum failure\n"); 268 return false; 269 } 270 271 return true; 272} 273 274BOOT_CODE uint32_t acpi_madt_scan( 275 acpi_rsdp_t *acpi_rsdp, 276 cpu_id_t *cpu_list, 277 uint32_t *num_ioapic, 278 paddr_t *ioapic_paddrs 279) 280{ 281 unsigned int entries; 282 uint32_t num_cpu; 283 uint32_t count; 284 acpi_madt_t *acpi_madt; 285 acpi_madt_header_t *acpi_madt_header; 286 287 acpi_rsdt_t *acpi_rsdt_mapped; 288 acpi_madt_t *acpi_madt_mapped; 289 acpi_rsdt_mapped = (acpi_rsdt_t *)acpi_table_init((acpi_rsdt_t *)(word_t)acpi_rsdp->rsdt_address, ACPI_RSDT); 290 291 num_cpu = 0; 292 *num_ioapic = 0; 293 294 assert(acpi_rsdt_mapped->header.length >= sizeof(acpi_header_t)); 295 /* Divide by uint32_t explicitly as this is the size as mandated by the ACPI standard */ 296 entries = (acpi_rsdt_mapped->header.length - sizeof(acpi_header_t)) / sizeof(uint32_t); 297 for (count = 0; count < entries; count++) { 298 acpi_madt = (acpi_madt_t *)(word_t)acpi_rsdt_mapped->entry[count]; 299 acpi_madt_mapped = (acpi_madt_t *)acpi_table_init(acpi_madt, ACPI_RSDT); 300 301 if (strncmp(acpi_str_apic, acpi_madt_mapped->header.signature, 4) == 0) { 302 printf("ACPI: MADT paddr=%p\n", acpi_madt); 303 printf("ACPI: MADT vaddr=%p\n", acpi_madt_mapped); 304 printf("ACPI: MADT apic_addr=0x%x\n", acpi_madt_mapped->apic_addr); 305 printf("ACPI: MADT flags=0x%x\n", acpi_madt_mapped->flags); 306 307 acpi_madt_header = (acpi_madt_header_t *)(acpi_madt_mapped + 1); 308 309 while ((char *)acpi_madt_header < (char *)acpi_madt_mapped + acpi_madt_mapped->header.length) { 310 switch (acpi_madt_header->type) { 311 /* ACPI specifies the following rules when listing APIC IDs: 312 * - Boot processor is listed first 313 * - For multi-threaded processors, BIOS should list the first logical 314 * processor of each of the individual multi-threaded processors in MADT 315 * before listing any of the second logical processors. 316 * - APIC IDs < 0xFF should be listed in APIC subtable, APIC IDs >= 0xFF 317 * should be listed in X2APIC subtable */ 318 case MADT_APIC: { 319 /* what Intel calls apic_id is what is called cpu_id in seL4! */ 320 uint8_t cpu_id = ((acpi_madt_apic_t *)acpi_madt_header)->apic_id; 321 uint32_t flags = ((acpi_madt_apic_t *)acpi_madt_header)->flags; 322 if (flags == 1) { 323 printf("ACPI: MADT_APIC apic_id=0x%x\n", cpu_id); 324 if (num_cpu == CONFIG_MAX_NUM_NODES) { 325 printf("ACPI: Not recording this APIC, only support %d\n", CONFIG_MAX_NUM_NODES); 326 } else { 327 cpu_list[num_cpu] = cpu_id; 328 num_cpu++; 329 } 330 } 331 break; 332 } 333 case MADT_x2APIC: { 334 uint32_t cpu_id = ((acpi_madt_x2apic_t *)acpi_madt_header)->x2apic_id; 335 uint32_t flags = ((acpi_madt_x2apic_t *)acpi_madt_header)->flags; 336 if (flags == 1) { 337 printf("ACPI: MADT_x2APIC apic_id=0x%x\n", cpu_id); 338 if (num_cpu == CONFIG_MAX_NUM_NODES) { 339 printf("ACPI: Not recording this APIC, only support %d\n", CONFIG_MAX_NUM_NODES); 340 } else { 341 cpu_list[num_cpu] = cpu_id; 342 num_cpu++; 343 } 344 } 345 break; 346 } 347 case MADT_IOAPIC: 348 printf( 349 "ACPI: MADT_IOAPIC ioapic_id=%d ioapic_addr=0x%x gsib=%d\n", 350 ((acpi_madt_ioapic_t *)acpi_madt_header)->ioapic_id, 351 ((acpi_madt_ioapic_t *)acpi_madt_header)->ioapic_addr, 352 ((acpi_madt_ioapic_t *)acpi_madt_header)->gsib 353 ); 354 if (*num_ioapic == CONFIG_MAX_NUM_IOAPIC) { 355 printf("ACPI: Not recording this IOAPIC, only support %d\n", CONFIG_MAX_NUM_IOAPIC); 356 } else { 357 ioapic_paddrs[*num_ioapic] = ((acpi_madt_ioapic_t *)acpi_madt_header)->ioapic_addr; 358 (*num_ioapic)++; 359 } 360 break; 361 case MADT_ISO: 362 printf("ACPI: MADT_ISO bus=%d source=%d gsi=%d flags=0x%x\n", 363 ((acpi_madt_iso_t *)acpi_madt_header)->bus, 364 ((acpi_madt_iso_t *)acpi_madt_header)->source, 365 ((acpi_madt_iso_t *)acpi_madt_header)->gsi, 366 ((acpi_madt_iso_t *)acpi_madt_header)->flags); 367 break; 368 default: 369 break; 370 } 371 acpi_madt_header = (acpi_madt_header_t *)((char *)acpi_madt_header + acpi_madt_header->length); 372 } 373 } 374 } 375 376 printf("ACPI: %d CPU(s) detected\n", num_cpu); 377 378 return num_cpu; 379} 380 381BOOT_CODE bool_t acpi_fadt_scan( 382 acpi_rsdp_t *acpi_rsdp 383) 384{ 385 unsigned int entries; 386 uint32_t count; 387 acpi_fadt_t *acpi_fadt; 388 389 acpi_rsdt_t *acpi_rsdt_mapped; 390 acpi_fadt_t *acpi_fadt_mapped; 391 acpi_rsdt_mapped = (acpi_rsdt_t *)acpi_table_init((acpi_rsdt_t *)(word_t)acpi_rsdp->rsdt_address, ACPI_RSDT); 392 393 assert(acpi_rsdt_mapped->header.length >= sizeof(acpi_header_t)); 394 /* Divide by uint32_t explicitly as this is the size as mandated by the ACPI standard */ 395 entries = (acpi_rsdt_mapped->header.length - sizeof(acpi_header_t)) / sizeof(uint32_t); 396 for (count = 0; count < entries; count++) { 397 acpi_fadt = (acpi_fadt_t *)(word_t)acpi_rsdt_mapped->entry[count]; 398 acpi_fadt_mapped = (acpi_fadt_t *)acpi_table_init(acpi_fadt, ACPI_RSDT); 399 400 if (strncmp(acpi_str_fadt, acpi_fadt_mapped->header.signature, 4) == 0) { 401 printf("ACPI: FADT paddr=%p\n", acpi_fadt); 402 printf("ACPI: FADT vaddr=%p\n", acpi_fadt_mapped); 403 printf("ACPI: FADT flags=0x%x\n", acpi_fadt_mapped->flags); 404 405 if (config_set(CONFIG_USE_LOGICAL_IDS) && 406 acpi_fadt_mapped->flags & BIT(19)) { 407 printf("system requires apic physical mode\n"); 408 return false; 409 } 410 } 411 } 412 413 return true; 414} 415 416BOOT_CODE void acpi_dmar_scan( 417 acpi_rsdp_t *acpi_rsdp, 418 paddr_t *drhu_list, 419 uint32_t *num_drhu, 420 uint32_t max_drhu_list_len, 421 acpi_rmrr_list_t *rmrr_list 422) 423{ 424 word_t i; 425 unsigned int entries; 426 uint32_t count; 427 uint32_t reg_basel, reg_baseh; 428 int rmrr_count; 429 dev_id_t dev_id; 430 431 acpi_dmar_t *acpi_dmar; 432 acpi_dmar_header_t *acpi_dmar_header; 433 acpi_dmar_rmrr_t *acpi_dmar_rmrr; 434 acpi_dmar_devscope_t *acpi_dmar_devscope; 435 436 acpi_rsdt_t *acpi_rsdt_mapped; 437 acpi_dmar_t *acpi_dmar_mapped; 438 439 acpi_rsdt_mapped = (acpi_rsdt_t *)acpi_table_init((acpi_rsdt_t *)(word_t)acpi_rsdp->rsdt_address, ACPI_RSDT); 440 441 *num_drhu = 0; 442 rmrr_count = 0; 443 444 assert(acpi_rsdt_mapped->header.length >= sizeof(acpi_header_t)); 445 entries = (acpi_rsdt_mapped->header.length - sizeof(acpi_header_t)) / sizeof(uint32_t); 446 for (count = 0; count < entries; count++) { 447 acpi_dmar = (acpi_dmar_t *)(word_t)acpi_rsdt_mapped->entry[count]; 448 acpi_dmar_mapped = (acpi_dmar_t *)acpi_table_init(acpi_dmar, ACPI_RSDT); 449 450 if (strncmp(acpi_str_dmar, acpi_dmar_mapped->header.signature, 4) == 0) { 451 printf("ACPI: DMAR paddr=%p\n", acpi_dmar); 452 printf("ACPI: DMAR vaddr=%p\n", acpi_dmar_mapped); 453 printf("ACPI: IOMMU host address width: %d\n", acpi_dmar_mapped->host_addr_width + 1); 454 acpi_dmar_header = (acpi_dmar_header_t *)(acpi_dmar_mapped + 1); 455 456 while ((char *)acpi_dmar_header < (char *)acpi_dmar_mapped + acpi_dmar_mapped->header.length) { 457 switch (acpi_dmar_header->type) { 458 459 case DMAR_DRHD: 460 if (*num_drhu == max_drhu_list_len) { 461 printf("ACPI: too many IOMMUs, disabling IOMMU support\n"); 462 /* try to increase MAX_NUM_DRHU in config.h */ 463 *num_drhu = 0; /* report zero IOMMUs */ 464 return; 465 } 466 reg_basel = ((acpi_dmar_drhd_t *)acpi_dmar_header)->reg_base[0]; 467 reg_baseh = ((acpi_dmar_drhd_t *)acpi_dmar_header)->reg_base[1]; 468 /* check if value fits into uint32_t */ 469 if (reg_baseh != 0) { 470 printf("ACPI: DMAR_DRHD reg_base exceeds 32 bit, disabling IOMMU support\n"); 471 /* try to make BIOS map it below 4G */ 472 *num_drhu = 0; /* report zero IOMMUs */ 473 return; 474 } 475 drhu_list[*num_drhu] = (paddr_t)reg_basel; 476 (*num_drhu)++; 477 break; 478 479 case DMAR_RMRR: 480 /* loop through all device scopes of this RMRR */ 481 acpi_dmar_rmrr = (acpi_dmar_rmrr_t *)acpi_dmar_header; 482 if (acpi_dmar_rmrr->reg_base[1] != 0 || 483 acpi_dmar_rmrr->reg_limit[1] != 0) { 484 printf("ACPI: RMRR device above 4GiB, disabling IOMMU support\n"); 485 *num_drhu = 0; 486 return ; 487 } 488 489 for (i = 0; i <= (acpi_dmar_header->length - sizeof(acpi_dmar_rmrr_t)) / sizeof(acpi_dmar_devscope_t); i++) { 490 acpi_dmar_devscope = &acpi_dmar_rmrr->devscope_0 + i; 491 492 if (acpi_dmar_devscope->type != 1) { 493 /* FIXME - bugzilla bug 170 */ 494 printf("ACPI: RMRR device scope: non-PCI-Endpoint-Devices not supported yet, disabling IOMMU support\n"); 495 *num_drhu = 0; /* report zero IOMMUs */ 496 return; 497 } 498 499 if (acpi_dmar_devscope->length > sizeof(acpi_dmar_devscope_t)) { 500 /* FIXME - bugzilla bug 170 */ 501 printf("ACPI: RMRR device scope: devices behind bridges not supported yet, disabling IOMMU support\n"); 502 *num_drhu = 0; /* report zero IOMMUs */ 503 return; 504 } 505 506 dev_id = 507 get_dev_id( 508 acpi_dmar_devscope->start_bus, 509 acpi_dmar_devscope->path_0.dev, 510 acpi_dmar_devscope->path_0.fun 511 ); 512 513 if (rmrr_count == CONFIG_MAX_RMRR_ENTRIES) { 514 printf("ACPI: Too many RMRR entries, disabling IOMMU support\n"); 515 *num_drhu = 0; 516 return; 517 } 518 printf("\tACPI: registering RMRR entry for region for device: bus=0x%x dev=0x%x fun=0x%x\n", 519 acpi_dmar_devscope->start_bus, 520 acpi_dmar_devscope->path_0.dev, 521 acpi_dmar_devscope->path_0.fun 522 ); 523 524 rmrr_list->entries[rmrr_count].device = dev_id; 525 rmrr_list->entries[rmrr_count].base = acpi_dmar_rmrr->reg_base[0]; 526 rmrr_list->entries[rmrr_count].limit = acpi_dmar_rmrr->reg_limit[0]; 527 rmrr_count++; 528 } 529 break; 530 531 case DMAR_ATSR: 532 /* not implemented yet */ 533 break; 534 535 default: 536 printf("ACPI: Unknown DMA remapping structure type: %x\n", acpi_dmar_header->type); 537 } 538 acpi_dmar_header = (acpi_dmar_header_t *)((char *)acpi_dmar_header + acpi_dmar_header->length); 539 } 540 } 541 } 542 rmrr_list->num = rmrr_count; 543 printf("ACPI: %d IOMMUs detected\n", *num_drhu); 544} 545