xv6

port of xv6 to x86-64
git clone http://frotz.net/git/xv6.git
Log | Files | Refs | README | LICENSE

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 }