madt.c revision 123326
1/*- 2 * Copyright (c) 2001 Doug Rabson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: head/sys/ia64/acpica/madt.c 123326 2003-12-09 03:04:19Z njl $ 27 */ 28 29#include "acpi.h" 30 31#include <machine/md_var.h> 32 33extern u_int64_t ia64_lapic_address; 34 35struct sapic *sapic_create(int, int, u_int64_t); 36 37static void 38print_entry(APIC_HEADER *entry) 39{ 40 41 switch (entry->Type) { 42 case APIC_XRUPT_OVERRIDE: { 43 MADT_INTERRUPT_OVERRIDE *iso = 44 (MADT_INTERRUPT_OVERRIDE *)entry; 45 printf("\tInterrupt source override entry\n"); 46 printf("\t\tBus=%d, Source=%d, Irq=0x%x\n", iso->Bus, 47 iso->Source, iso->Interrupt); 48 break; 49 } 50 51 case APIC_IO: 52 printf("\tI/O APIC entry\n"); 53 break; 54 55 case APIC_IO_SAPIC: { 56 MADT_IO_SAPIC *sapic = (MADT_IO_SAPIC *)entry; 57 printf("\tI/O SAPIC entry\n"); 58 printf("\t\tId=0x%x, InterruptBase=0x%x, Address=0x%lx\n", 59 sapic->IoSapicId, sapic->InterruptBase, sapic->Address); 60 break; 61 } 62 63 case APIC_LOCAL_NMI: 64 printf("\tLocal APIC NMI entry\n"); 65 break; 66 67 case APIC_ADDRESS_OVERRIDE: { 68 MADT_ADDRESS_OVERRIDE *lapic = (MADT_ADDRESS_OVERRIDE *)entry; 69 printf("\tLocal APIC override entry\n"); 70 printf("\t\tLocal APIC address=0x%jx\n", lapic->Address); 71 break; 72 } 73 74 case APIC_LOCAL_SAPIC: { 75 MADT_LOCAL_SAPIC *sapic = (MADT_LOCAL_SAPIC *)entry; 76 printf("\tLocal SAPIC entry\n"); 77 printf("\t\tProcessorId=0x%x, Id=0x%x, Eid=0x%x", 78 sapic->ProcessorId, sapic->LocalSapicId, 79 sapic->LocalSapicEid); 80 if (!sapic->ProcessorEnabled) 81 printf(" (disabled)"); 82 printf("\n"); 83 break; 84 } 85 86 case APIC_NMI: 87 printf("\tNMI entry\n"); 88 break; 89 90 case APIC_XRUPT_SOURCE: { 91 MADT_INTERRUPT_SOURCE *pis = (MADT_INTERRUPT_SOURCE *)entry; 92 printf("\tPlatform interrupt entry\n"); 93 printf("\t\tPolarity=%d, TriggerMode=%d, Id=0x%x, " 94 "Eid=0x%x, Vector=0x%x, Irq=%d\n", 95 pis->Polarity, pis->TriggerMode, pis->ProcessorId, 96 pis->ProcessorEid, pis->IoSapicVector, pis->Interrupt); 97 break; 98 } 99 100 case APIC_PROCESSOR: 101 printf("\tLocal APIC entry\n"); 102 break; 103 104 default: 105 printf("\tUnknown type %d entry\n", entry->Type); 106 break; 107 } 108} 109 110void 111ia64_probe_sapics(void) 112{ 113 ACPI_POINTER rsdp_ptr; 114 APIC_HEADER *entry; 115 MULTIPLE_APIC_TABLE *table; 116 RSDP_DESCRIPTOR *rsdp; 117 XSDT_DESCRIPTOR *xsdt; 118 char *end, *p; 119 int t, tables; 120 121 if (AcpiOsGetRootPointer(ACPI_LOGICAL_ADDRESSING, &rsdp_ptr) != AE_OK) 122 return; 123 124 rsdp = (RSDP_DESCRIPTOR *)IA64_PHYS_TO_RR7(rsdp_ptr.Pointer.Physical); 125 xsdt = (XSDT_DESCRIPTOR *)IA64_PHYS_TO_RR7(rsdp->XsdtPhysicalAddress); 126 127 tables = (UINT64 *)((char *)xsdt + xsdt->Length) - 128 xsdt->TableOffsetEntry; 129 130 for (t = 0; t < tables; t++) { 131 table = (MULTIPLE_APIC_TABLE *) 132 IA64_PHYS_TO_RR7(xsdt->TableOffsetEntry[t]); 133 134 if (bootverbose) 135 printf("Table '%c%c%c%c' at %p\n", 136 table->Signature[0], table->Signature[1], 137 table->Signature[2], table->Signature[3], table); 138 139 if (strncmp(table->Signature, APIC_SIG, 4) != 0) 140 continue; 141 142 /* Save the address of the processor interrupt block. */ 143 if (bootverbose) 144 printf("\tLocal APIC address=0x%x\n", 145 table->LocalApicAddress); 146 ia64_lapic_address = table->LocalApicAddress; 147 148 end = (char *)table + table->Length; 149 p = (char *)(table + 1); 150 while (p < end) { 151 entry = (APIC_HEADER *)p; 152 153 if (bootverbose) 154 print_entry(entry); 155 156 switch (entry->Type) { 157 case APIC_IO_SAPIC: { 158 MADT_IO_SAPIC *sapic = (MADT_IO_SAPIC *)entry; 159 sapic_create(sapic->IoSapicId, 160 sapic->InterruptBase, sapic->Address); 161 break; 162 } 163 164 case APIC_ADDRESS_OVERRIDE: { 165 MADT_ADDRESS_OVERRIDE *lapic = 166 (MADT_ADDRESS_OVERRIDE*)entry; 167 ia64_lapic_address = lapic->Address; 168 break; 169 } 170 171#ifdef SMP 172 case APIC_LOCAL_SAPIC: { 173 MADT_LOCAL_SAPIC *sapic = 174 (MADT_LOCAL_SAPIC *)entry; 175 if (sapic->ProcessorEnabled) 176 cpu_mp_add(sapic->ProcessorId, 177 sapic->LocalSapicId, 178 sapic->LocalSapicEid); 179 break; 180 } 181#endif 182 183 default: 184 break; 185 } 186 187 p += entry->Length; 188 } 189 } 190} 191 192/* 193 * Count the number of local SAPIC entries in the APIC table. Every enabled 194 * entry corresponds to a processor. 195 */ 196int 197ia64_count_cpus(void) 198{ 199 ACPI_POINTER rsdp_ptr; 200 MULTIPLE_APIC_TABLE *table; 201 MADT_LOCAL_SAPIC *entry; 202 RSDP_DESCRIPTOR *rsdp; 203 XSDT_DESCRIPTOR *xsdt; 204 char *end, *p; 205 int cpus, t, tables; 206 207 if (AcpiOsGetRootPointer(ACPI_LOGICAL_ADDRESSING, &rsdp_ptr) != AE_OK) 208 return (0); 209 210 rsdp = (RSDP_DESCRIPTOR *)IA64_PHYS_TO_RR7(rsdp_ptr.Pointer.Physical); 211 xsdt = (XSDT_DESCRIPTOR *)IA64_PHYS_TO_RR7(rsdp->XsdtPhysicalAddress); 212 213 tables = (UINT64 *)((char *)xsdt + xsdt->Length) - 214 xsdt->TableOffsetEntry; 215 216 cpus = 0; 217 218 for (t = 0; t < tables; t++) { 219 table = (MULTIPLE_APIC_TABLE *) 220 IA64_PHYS_TO_RR7(xsdt->TableOffsetEntry[t]); 221 222 if (strncmp(table->Signature, APIC_SIG, 4) != 0) 223 continue; 224 225 end = (char *)table + table->Length; 226 p = (char *)(table + 1); 227 while (p < end) { 228 entry = (MADT_LOCAL_SAPIC *)p; 229 230 if (entry->Type == APIC_LOCAL_SAPIC && 231 entry->ProcessorEnabled) 232 cpus++; 233 234 p += entry->Length; 235 } 236 } 237 238 return (cpus); 239} 240