madt.c revision 119867
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 119867 2003-09-07 23:09:08Z marcel $ 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 37#pragma pack(1) 38 39#define APIC_INTERRUPT_SOURCE_OVERRIDE 2 40#define APIC_NMI 3 41#define APIC_LOCAL_APIC_NMI 4 42#define APIC_LOCAL_APIC_OVERRIDE 5 43#define APIC_IO_SAPIC 6 44#define APIC_LOCAL_SAPIC 7 45#define APIC_PLATFORM_INTERRUPT 8 46 47typedef struct /* Interrupt Source Override */ 48{ 49 APIC_HEADER Header; 50 UINT8 Bus; 51 UINT8 Source; 52 UINT32 GlobalSystemInterrupt; 53 UINT16 Flags; 54} INTERRUPT_SOURCE_OVERRIDE; 55 56typedef struct /* IO SAPIC */ 57{ 58 APIC_HEADER Header; 59 UINT8 IoSapicId; /* I/O SAPIC ID */ 60 UINT8 Reserved; /* reserved - must be zero */ 61 UINT32 Vector; /* interrupt base */ 62 UINT64 IoSapicAddress; /* SAPIC's physical address */ 63} IO_SAPIC; 64 65typedef struct /* LOCAL SAPIC */ 66{ 67 APIC_HEADER Header; 68 UINT8 ProcessorId; /* ACPI processor id */ 69 UINT8 LocalSapicId; /* Processor local SAPIC id */ 70 UINT8 LocalSapicEid; /* Processor local SAPIC eid */ 71 UINT8 Reserved[3]; 72 UINT32 ProcessorEnabled: 1; 73 UINT32 FlagsReserved: 31; 74} LOCAL_SAPIC; 75 76typedef struct /* LOCAL APIC OVERRIDE */ 77{ 78 APIC_HEADER Header; 79 UINT16 Reserved; 80 UINT64 LocalApicAddress; 81} LAPIC_OVERRIDE; 82 83typedef struct /* PLATFORM INTERRUPT SOURCE */ 84{ 85 APIC_HEADER Header; 86 UINT16 Polarity : 2; /* Polarity of input signal */ 87 UINT16 TriggerMode: 2; /* Trigger mode of input signal */ 88 UINT16 Reserved1 : 12; 89 UINT8 InterruptType; /* 1-PMI, 2-INIT, 3-Error */ 90 UINT8 ProcessorId; /* Processor ID of destination */ 91 UINT8 ProcessorEid; /* Processor EID of destination */ 92 UINT8 IoSapicVector; /* Value for redirection table */ 93 UINT32 GlobalSystemInterrupt; /* Global System Interrupt */ 94 UINT32 Reserved2; 95} PLATFORM_INTERRUPT_SOURCE; 96 97#pragma pack() 98 99static void 100print_entry(APIC_HEADER *entry) 101{ 102 103 switch (entry->Type) { 104 case APIC_INTERRUPT_SOURCE_OVERRIDE: { 105 INTERRUPT_SOURCE_OVERRIDE *iso = 106 (INTERRUPT_SOURCE_OVERRIDE *)entry; 107 printf("\tInterrupt source override entry\n"); 108 printf("\t\tBus=%d, Source=%d, Irq=0x%x\n", iso->Bus, 109 iso->Source, iso->GlobalSystemInterrupt); 110 break; 111 } 112 113 case APIC_IO: 114 printf("\tI/O APIC entry\n"); 115 break; 116 117 case APIC_IO_SAPIC: { 118 IO_SAPIC *sapic = (IO_SAPIC *)entry; 119 printf("\tI/O SAPIC entry\n"); 120 printf("\t\tId=0x%x, Vector=0x%x, Address=0x%lx\n", 121 sapic->IoSapicId, sapic->Vector, sapic->IoSapicAddress); 122 break; 123 } 124 125 case APIC_LOCAL_APIC_NMI: 126 printf("\tLocal APIC NMI entry\n"); 127 break; 128 129 case APIC_LOCAL_APIC_OVERRIDE: { 130 LAPIC_OVERRIDE *lapic = (LAPIC_OVERRIDE *)entry; 131 printf("\tLocal APIC override entry\n"); 132 printf("\t\tLocal APIC address=0x%lx\n", 133 lapic->LocalApicAddress); 134 break; 135 } 136 137 case APIC_LOCAL_SAPIC: { 138 LOCAL_SAPIC *sapic = (LOCAL_SAPIC *)entry; 139 printf("\tLocal SAPIC entry\n"); 140 printf("\t\tProcessorId=0x%x, Id=0x%x, Eid=0x%x", 141 sapic->ProcessorId, sapic->LocalSapicId, 142 sapic->LocalSapicEid); 143 if (!sapic->ProcessorEnabled) 144 printf(" (disabled)"); 145 printf("\n"); 146 break; 147 } 148 149 case APIC_NMI: 150 printf("\tNMI entry\n"); 151 break; 152 153 case APIC_PLATFORM_INTERRUPT: { 154 PLATFORM_INTERRUPT_SOURCE *pis = 155 (PLATFORM_INTERRUPT_SOURCE *)entry; 156 printf("\tPlatform interrupt entry\n"); 157 printf("\t\tPolarity=%d, TriggerMode=%d, Id=0x%x, " 158 "Eid=0x%x, Vector=0x%x, Irq=%d\n", 159 pis->Polarity, pis->TriggerMode, pis->ProcessorId, 160 pis->ProcessorEid, pis->IoSapicVector, 161 pis->GlobalSystemInterrupt); 162 break; 163 } 164 165 case APIC_PROC: 166 printf("\tLocal APIC entry\n"); 167 break; 168 169 default: 170 printf("\tUnknown type %d entry\n", entry->Type); 171 break; 172 } 173} 174 175void 176ia64_probe_sapics(void) 177{ 178 ACPI_POINTER rsdp_ptr; 179 APIC_HEADER *entry; 180 APIC_TABLE *table; 181 RSDP_DESCRIPTOR *rsdp; 182 XSDT_DESCRIPTOR *xsdt; 183 char *end, *p; 184 int t, tables; 185 186 if (AcpiOsGetRootPointer(ACPI_LOGICAL_ADDRESSING, &rsdp_ptr) != AE_OK) 187 return; 188 189 rsdp = (RSDP_DESCRIPTOR *)IA64_PHYS_TO_RR7(rsdp_ptr.Pointer.Physical); 190 xsdt = (XSDT_DESCRIPTOR *)IA64_PHYS_TO_RR7(rsdp->XsdtPhysicalAddress); 191 192 tables = (UINT64 *)((char *)xsdt + xsdt->Header.Length) - 193 xsdt->TableOffsetEntry; 194 195 for (t = 0; t < tables; t++) { 196 table = (APIC_TABLE *) 197 IA64_PHYS_TO_RR7(xsdt->TableOffsetEntry[t]); 198 199 if (bootverbose) 200 printf("Table '%c%c%c%c' at %p\n", 201 table->Header.Signature[0], 202 table->Header.Signature[1], 203 table->Header.Signature[2], 204 table->Header.Signature[3], table); 205 206 if (strncmp(table->Header.Signature, APIC_SIG, 4) != 0) 207 continue; 208 209 /* Save the address of the processor interrupt block. */ 210 if (bootverbose) 211 printf("\tLocal APIC address=0x%x\n", 212 table->LocalApicAddress); 213 ia64_lapic_address = table->LocalApicAddress; 214 215 end = (char *)table + table->Header.Length; 216 p = (char *)(table + 1); 217 while (p < end) { 218 entry = (APIC_HEADER *)p; 219 220 if (bootverbose) 221 print_entry(entry); 222 223 switch (entry->Type) { 224 case APIC_IO_SAPIC: { 225 IO_SAPIC *sapic = (IO_SAPIC *)entry; 226 sapic_create(sapic->IoSapicId, sapic->Vector, 227 sapic->IoSapicAddress); 228 break; 229 } 230 231 case APIC_LOCAL_APIC_OVERRIDE: { 232 LAPIC_OVERRIDE *lapic = (LAPIC_OVERRIDE*)entry; 233 ia64_lapic_address = lapic->LocalApicAddress; 234 break; 235 } 236 237#ifdef SMP 238 case APIC_LOCAL_SAPIC: { 239 LOCAL_SAPIC *sapic = (LOCAL_SAPIC *)entry; 240 if (sapic->ProcessorEnabled) 241 cpu_mp_add(sapic->ProcessorId, 242 sapic->LocalSapicId, 243 sapic->LocalSapicEid); 244 break; 245 } 246#endif 247 248 default: 249 break; 250 } 251 252 p += entry->Length; 253 } 254 } 255} 256 257/* 258 * Count the number of local SAPIC entries in the APIC table. Every enabled 259 * entry corresponds to a processor. 260 */ 261int 262ia64_count_cpus(void) 263{ 264 ACPI_POINTER rsdp_ptr; 265 APIC_TABLE *table; 266 LOCAL_SAPIC *entry; 267 RSDP_DESCRIPTOR *rsdp; 268 XSDT_DESCRIPTOR *xsdt; 269 char *end, *p; 270 int cpus, t, tables; 271 272 if (AcpiOsGetRootPointer(ACPI_LOGICAL_ADDRESSING, &rsdp_ptr) != AE_OK) 273 return (0); 274 275 rsdp = (RSDP_DESCRIPTOR *)IA64_PHYS_TO_RR7(rsdp_ptr.Pointer.Physical); 276 xsdt = (XSDT_DESCRIPTOR *)IA64_PHYS_TO_RR7(rsdp->XsdtPhysicalAddress); 277 278 tables = (UINT64 *)((char *)xsdt + xsdt->Header.Length) - 279 xsdt->TableOffsetEntry; 280 281 cpus = 0; 282 283 for (t = 0; t < tables; t++) { 284 table = (APIC_TABLE *) 285 IA64_PHYS_TO_RR7(xsdt->TableOffsetEntry[t]); 286 287 if (strncmp(table->Header.Signature, APIC_SIG, 4) != 0) 288 continue; 289 290 end = (char *)table + table->Header.Length; 291 p = (char *)(table + 1); 292 while (p < end) { 293 entry = (LOCAL_SAPIC *)p; 294 295 if (entry->Header.Type == APIC_LOCAL_SAPIC && 296 entry->ProcessorEnabled) 297 cpus++; 298 299 p += entry->Header.Length; 300 } 301 } 302 303 return (cpus); 304} 305