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