madt.c revision 119946
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 119946 2003-09-10 06:32:27Z jhb $ 27 */ 28 29#include "acpi.h" 30#include <dev/acpica/madt.h> 31 32#include <machine/md_var.h> 33 34extern u_int64_t ia64_lapic_address; 35 36struct sapic *sapic_create(int, int, u_int64_t); 37 38static void 39print_entry(APIC_HEADER *entry) 40{ 41 42 switch (entry->Type) { 43 case APIC_INTERRUPT_SOURCE_OVERRIDE: { 44 INTERRUPT_SOURCE_OVERRIDE *iso = 45 (INTERRUPT_SOURCE_OVERRIDE *)entry; 46 printf("\tInterrupt source override entry\n"); 47 printf("\t\tBus=%d, Source=%d, Irq=0x%x\n", iso->Bus, 48 iso->Source, iso->GlobalSystemInterrupt); 49 break; 50 } 51 52 case APIC_IO: 53 printf("\tI/O APIC entry\n"); 54 break; 55 56 case APIC_IO_SAPIC: { 57 IO_SAPIC *sapic = (IO_SAPIC *)entry; 58 printf("\tI/O SAPIC entry\n"); 59 printf("\t\tId=0x%x, Vector=0x%x, Address=0x%lx\n", 60 sapic->IoSapicId, sapic->Vector, sapic->IoSapicAddress); 61 break; 62 } 63 64 case APIC_LOCAL_APIC_NMI: 65 printf("\tLocal APIC NMI entry\n"); 66 break; 67 68 case APIC_LOCAL_APIC_OVERRIDE: { 69 LAPIC_OVERRIDE *lapic = (LAPIC_OVERRIDE *)entry; 70 printf("\tLocal APIC override entry\n"); 71 printf("\t\tLocal APIC address=0x%lx\n", 72 lapic->LocalApicAddress); 73 break; 74 } 75 76 case APIC_LOCAL_SAPIC: { 77 LOCAL_SAPIC *sapic = (LOCAL_SAPIC *)entry; 78 printf("\tLocal SAPIC entry\n"); 79 printf("\t\tProcessorId=0x%x, Id=0x%x, Eid=0x%x", 80 sapic->ProcessorId, sapic->LocalSapicId, 81 sapic->LocalSapicEid); 82 if (!sapic->ProcessorEnabled) 83 printf(" (disabled)"); 84 printf("\n"); 85 break; 86 } 87 88 case APIC_NMI: 89 printf("\tNMI entry\n"); 90 break; 91 92 case APIC_PLATFORM_INTERRUPT: { 93 PLATFORM_INTERRUPT_SOURCE *pis = 94 (PLATFORM_INTERRUPT_SOURCE *)entry; 95 printf("\tPlatform interrupt entry\n"); 96 printf("\t\tPolarity=%d, TriggerMode=%d, Id=0x%x, " 97 "Eid=0x%x, Vector=0x%x, Irq=%d\n", 98 pis->Polarity, pis->TriggerMode, pis->ProcessorId, 99 pis->ProcessorEid, pis->IoSapicVector, 100 pis->GlobalSystemInterrupt); 101 break; 102 } 103 104 case APIC_PROC: 105 printf("\tLocal APIC entry\n"); 106 break; 107 108 default: 109 printf("\tUnknown type %d entry\n", entry->Type); 110 break; 111 } 112} 113 114void 115ia64_probe_sapics(void) 116{ 117 ACPI_POINTER rsdp_ptr; 118 APIC_HEADER *entry; 119 APIC_TABLE *table; 120 RSDP_DESCRIPTOR *rsdp; 121 XSDT_DESCRIPTOR *xsdt; 122 char *end, *p; 123 int t, tables; 124 125 if (AcpiOsGetRootPointer(ACPI_LOGICAL_ADDRESSING, &rsdp_ptr) != AE_OK) 126 return; 127 128 rsdp = (RSDP_DESCRIPTOR *)IA64_PHYS_TO_RR7(rsdp_ptr.Pointer.Physical); 129 xsdt = (XSDT_DESCRIPTOR *)IA64_PHYS_TO_RR7(rsdp->XsdtPhysicalAddress); 130 131 tables = (UINT64 *)((char *)xsdt + xsdt->Header.Length) - 132 xsdt->TableOffsetEntry; 133 134 for (t = 0; t < tables; t++) { 135 table = (APIC_TABLE *) 136 IA64_PHYS_TO_RR7(xsdt->TableOffsetEntry[t]); 137 138 if (bootverbose) 139 printf("Table '%c%c%c%c' at %p\n", 140 table->Header.Signature[0], 141 table->Header.Signature[1], 142 table->Header.Signature[2], 143 table->Header.Signature[3], table); 144 145 if (strncmp(table->Header.Signature, APIC_SIG, 4) != 0) 146 continue; 147 148 /* Save the address of the processor interrupt block. */ 149 if (bootverbose) 150 printf("\tLocal APIC address=0x%x\n", 151 table->LocalApicAddress); 152 ia64_lapic_address = table->LocalApicAddress; 153 154 end = (char *)table + table->Header.Length; 155 p = (char *)(table + 1); 156 while (p < end) { 157 entry = (APIC_HEADER *)p; 158 159 if (bootverbose) 160 print_entry(entry); 161 162 switch (entry->Type) { 163 case APIC_IO_SAPIC: { 164 IO_SAPIC *sapic = (IO_SAPIC *)entry; 165 sapic_create(sapic->IoSapicId, sapic->Vector, 166 sapic->IoSapicAddress); 167 break; 168 } 169 170 case APIC_LOCAL_APIC_OVERRIDE: { 171 LAPIC_OVERRIDE *lapic = (LAPIC_OVERRIDE*)entry; 172 ia64_lapic_address = lapic->LocalApicAddress; 173 break; 174 } 175 176#ifdef SMP 177 case APIC_LOCAL_SAPIC: { 178 LOCAL_SAPIC *sapic = (LOCAL_SAPIC *)entry; 179 if (sapic->ProcessorEnabled) 180 cpu_mp_add(sapic->ProcessorId, 181 sapic->LocalSapicId, 182 sapic->LocalSapicEid); 183 break; 184 } 185#endif 186 187 default: 188 break; 189 } 190 191 p += entry->Length; 192 } 193 } 194} 195 196/* 197 * Count the number of local SAPIC entries in the APIC table. Every enabled 198 * entry corresponds to a processor. 199 */ 200int 201ia64_count_cpus(void) 202{ 203 ACPI_POINTER rsdp_ptr; 204 APIC_TABLE *table; 205 LOCAL_SAPIC *entry; 206 RSDP_DESCRIPTOR *rsdp; 207 XSDT_DESCRIPTOR *xsdt; 208 char *end, *p; 209 int cpus, t, tables; 210 211 if (AcpiOsGetRootPointer(ACPI_LOGICAL_ADDRESSING, &rsdp_ptr) != AE_OK) 212 return (0); 213 214 rsdp = (RSDP_DESCRIPTOR *)IA64_PHYS_TO_RR7(rsdp_ptr.Pointer.Physical); 215 xsdt = (XSDT_DESCRIPTOR *)IA64_PHYS_TO_RR7(rsdp->XsdtPhysicalAddress); 216 217 tables = (UINT64 *)((char *)xsdt + xsdt->Header.Length) - 218 xsdt->TableOffsetEntry; 219 220 cpus = 0; 221 222 for (t = 0; t < tables; t++) { 223 table = (APIC_TABLE *) 224 IA64_PHYS_TO_RR7(xsdt->TableOffsetEntry[t]); 225 226 if (strncmp(table->Header.Signature, APIC_SIG, 4) != 0) 227 continue; 228 229 end = (char *)table + table->Header.Length; 230 p = (char *)(table + 1); 231 while (p < end) { 232 entry = (LOCAL_SAPIC *)p; 233 234 if (entry->Header.Type == APIC_LOCAL_SAPIC && 235 entry->ProcessorEnabled) 236 cpus++; 237 238 p += entry->Header.Length; 239 } 240 } 241 242 return (cpus); 243} 244