acpi.c (4470B)
1 /* vm64.c 2 * 3 * Copyright (c) 2013 Brian Swetland 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining 6 * a copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sublicense, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be 14 * included in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 * 24 */ 25 26 #include "types.h" 27 #include "defs.h" 28 #include "param.h" 29 #include "memlayout.h" 30 #include "mp.h" 31 #include "x86.h" 32 #include "mmu.h" 33 #include "proc.h" 34 #include "acpi.h" 35 36 extern struct cpu cpus[NCPU]; 37 extern int ismp; 38 extern int ncpu; 39 extern uchar ioapicid; 40 41 static struct acpi_rdsp *scan_rdsp(uint base, uint len) { 42 uchar *p; 43 for (p = p2v(base); len >= sizeof(struct acpi_rdsp); len -= 4, p += 4) { 44 if (memcmp(p, SIG_RDSP, 8) == 0) { 45 uint sum, n; 46 for (sum = 0, n = 0; n < 20; n++) 47 sum += p[n]; 48 if ((sum & 0xff) == 0) 49 return (struct acpi_rdsp *) p; 50 } 51 } 52 return (struct acpi_rdsp *) 0; 53 } 54 55 static struct acpi_rdsp *find_rdsp(void) { 56 struct acpi_rdsp *rdsp; 57 uintp pa; 58 pa = *((ushort*) P2V(0x40E)) << 4; // EBDA 59 if (pa && (rdsp = scan_rdsp(pa, 1024))) 60 return rdsp; 61 return scan_rdsp(0xE0000, 0x20000); 62 } 63 64 static int acpi_config_smp(struct acpi_madt *madt) { 65 uint32 lapic_addr; 66 uint nioapic = 0; 67 uchar *p, *e; 68 69 if (!madt) 70 return -1; 71 if (madt->header.length < sizeof(struct acpi_madt)) 72 return -1; 73 74 lapic_addr = madt->lapic_addr_phys; 75 76 p = madt->table; 77 e = p + madt->header.length - sizeof(struct acpi_madt); 78 79 while (p < e) { 80 uint len; 81 if ((e - p) < 2) 82 break; 83 len = p[1]; 84 if ((e - p) < len) 85 break; 86 switch (p[0]) { 87 case TYPE_LAPIC: { 88 struct madt_lapic *lapic = (void*) p; 89 if (len < sizeof(*lapic)) 90 break; 91 if (!(lapic->flags & APIC_LAPIC_ENABLED)) 92 break; 93 cprintf("acpi: cpu#%d apicid %d\n", ncpu, lapic->apic_id); 94 cpus[ncpu].id = ncpu; 95 cpus[ncpu].apicid = lapic->apic_id; 96 ncpu++; 97 break; 98 } 99 case TYPE_IOAPIC: { 100 struct madt_ioapic *ioapic = (void*) p; 101 if (len < sizeof(*ioapic)) 102 break; 103 cprintf("acpi: ioapic#%d @%x id=%d base=%d\n", 104 nioapic, ioapic->addr, ioapic->id, ioapic->interrupt_base); 105 if (nioapic) { 106 cprintf("warning: multiple ioapics are not supported"); 107 } else { 108 ioapicid = ioapic->id; 109 } 110 nioapic++; 111 break; 112 } 113 } 114 p += len; 115 } 116 117 if (ncpu) { 118 ismp = 1; 119 lapic = IO2V(((uintp)lapic_addr)); 120 return 0; 121 } 122 123 return -1; 124 } 125 126 #if X64 127 #define PHYSLIMIT 0x80000000 128 #else 129 #define PHYSLIMIT 0x0E000000 130 #endif 131 132 int acpiinit(void) { 133 unsigned n, count; 134 struct acpi_rdsp *rdsp; 135 struct acpi_rsdt *rsdt; 136 struct acpi_madt *madt = 0; 137 138 rdsp = find_rdsp(); 139 if (rdsp->rsdt_addr_phys > PHYSLIMIT) 140 goto notmapped; 141 rsdt = p2v(rdsp->rsdt_addr_phys); 142 count = (rsdt->header.length - sizeof(*rsdt)) / 4; 143 for (n = 0; n < count; n++) { 144 struct acpi_desc_header *hdr = p2v(rsdt->entry[n]); 145 if (rsdt->entry[n] > PHYSLIMIT) 146 goto notmapped; 147 #if DEBUG 148 uchar sig[5], id[7], tableid[9], creator[5]; 149 memmove(sig, hdr->signature, 4); sig[4] = 0; 150 memmove(id, hdr->oem_id, 6); id[6] = 0; 151 memmove(tableid, hdr->oem_tableid, 8); tableid[8] = 0; 152 memmove(creator, hdr->creator_id, 4); creator[4] = 0; 153 cprintf("acpi: %s %s %s %x %s %x\n", 154 sig, id, tableid, hdr->oem_revision, 155 creator, hdr->creator_revision); 156 #endif 157 if (!memcmp(hdr->signature, SIG_MADT, 4)) 158 madt = (void*) hdr; 159 } 160 161 return acpi_config_smp(madt); 162 163 notmapped: 164 cprintf("acpi: tables above 0x%x not mapped.\n", PHYSLIMIT); 165 return -1; 166 }