From 9f55eea1e04d587514c654f2a4398a4024ee4712 Mon Sep 17 00:00:00 2001
From: Liu, Jinsong <jinsong.liu@intel.com>
Date: Thu, 4 Feb 2010 17:08:43 +0800
Subject: [PATCH]     Setup vcpu add/remove infrastructure

        1. setup madt_info structure, so that static dsdt get
           run-time madt info like checksum address, lapic address,
           max cpu numbers, with least hardcode magic number (realmode
           address of madt_info).
        2. setup vcpu add/remove dsdt infrastructure, including processor
           related acpi objects and control methods. vcpu add/remove will
           trigger SCI and then control method _L02. By matching madt, vcpu
           number and add/remove action were found, then by notify control
           method, it will notify OS acpi driver.
        3. remove ssdt since currently it only has simple \_PR.
        4. set madt as ACPI NVS, so that os will not reclaim this area.

        Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
---
 src/acpi-dsdt.dsl |  126 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/acpi.c        |   83 +++++++++-------------------------
 2 files changed, 147 insertions(+), 62 deletions(-)

diff --git a/src/acpi-dsdt.dsl b/src/acpi-dsdt.dsl
index cc31112..abc524e 100644
--- a/src/acpi-dsdt.dsl
+++ b/src/acpi-dsdt.dsl
@@ -700,8 +700,11 @@ DefinitionBlock (
             Return (0x01)
 
         }
+        /*
+         * _L02 method for CPU notification
+         */
         Method(_L02) {
-            Return(0x01)
+            Return(\_PR.PRSC())
         }
         Method(_L03) {
             Return(0x01)
@@ -744,4 +747,125 @@ DefinitionBlock (
         }
     }
 
+
+    Scope (\_PR)
+    {
+        /* MADT_INFO_PHYSICAL_ADDRESS == 0x514 */
+        OperationRegion(MINF, SystemMemory, 0x514, 12)
+        Field(MINF, DwordAcc, NoLock, Preserve)
+        {
+            MSUA, 32, /* MADT checksum address */
+            MAPA, 32, /* MADT LAPIC0 address */
+            CPUN, 32  /* Max cpu number */
+        }
+
+        OperationRegion(MSUM, SystemMemory, MSUA, 1)
+        Field(MSUM, ByteAcc, NoLock, Preserve)
+        {
+            MSU, 8    /* MADT checksum */
+        }
+
+        #define gen_processor(nr, name)                                       \
+        Processor (C##name, nr, 0x0000b010, 0x06) {                           \
+            Name (_HID, "ACPI0007")                                           \
+            OperationRegion(MATR, SystemMemory, Add(MAPA, Multiply(nr,8)), 8) \
+            Field (MATR, ByteAcc, NoLock, Preserve)                           \
+            {                                                                 \
+                MAT, 64                                                       \
+            }                                                                 \
+            Field (MATR, ByteAcc, NoLock, Preserve)                           \
+            {                                                                 \
+                Offset(4),                                                    \
+                FLG, 1                                                        \
+            }                                                                 \
+            Method(_MAT, 0) {                                                 \
+                Return(ToBuffer(MAT))                                         \
+            }                                                                 \
+            Method (_STA) {                                                   \
+                If (FLG) { Return(0xF) } Else { Return(0x9) }                 \
+            }                                                                 \
+            Method (_EJ0, 1, NotSerialized) {                                 \
+                Sleep (0xC8)                                                  \
+            }                                                                 \
+        }                                                                     \
+
+        gen_processor(0, 0)
+        gen_processor(1, 1)
+        gen_processor(2, 2)
+        gen_processor(3, 3)
+        gen_processor(4, 4)
+        gen_processor(5, 5)
+        gen_processor(6, 6)
+        gen_processor(7, 7)
+        gen_processor(8, 8)
+        gen_processor(9, 9)
+        gen_processor(10, A)
+        gen_processor(11, B)
+        gen_processor(12, C)
+        gen_processor(13, D)
+        gen_processor(14, E)
+
+
+        Method (NTFY, 2) {
+        #define gen_ntfy(nr)                        \
+        If (LEqual(Arg0, 0x##nr)) {                 \
+            If (LNotEqual(Arg1, \_PR.C##nr.FLG)) {  \
+                Store (Arg1, \_PR.C##nr.FLG)        \
+                If (LEqual(Arg1, 1)) {              \
+                    Notify(C##nr, 1)                \
+                    Subtract(\_PR.MSU, 1, \_PR.MSU) \
+                } Else {                            \
+                    Notify(C##nr, 3)                \
+                    Add(\_PR.MSU, 1, \_PR.MSU)      \
+                }                                   \
+            }                                       \
+        }
+
+        gen_ntfy(0)
+        gen_ntfy(1)
+        gen_ntfy(2)
+        gen_ntfy(3)
+        gen_ntfy(4)
+        gen_ntfy(5)
+        gen_ntfy(6)
+        gen_ntfy(7)
+        gen_ntfy(8)
+        gen_ntfy(9)
+        gen_ntfy(A)
+        gen_ntfy(B)
+        gen_ntfy(C)
+        gen_ntfy(D)
+        gen_ntfy(E)
+
+        Return(One)
+        }
+
+
+        OperationRegion(PRST, SystemIO, 0xaf00, 32)
+        Field (PRST, ByteAcc, NoLock, Preserve)
+        {
+            PRS, 256
+        }
+
+        Method(PRSC, 0) {
+            Store(PRS, Local3)
+            Store(Zero, Local0)
+            While(LLess(Local0, 32)) {
+                Store(Zero, Local1)
+                Store(DerefOf(Index(Local3, Local0)), Local2)
+                While(LLess(Local1, 8)) {
+                    Store(Add(Multiply(Local0, 8), Local1), Local4)
+                    If(LLess(Local4, CPUN)) {
+                        NTFY(Local4, And(Local2, 1))
+                    } Else {
+                        Break
+                    }
+                    ShiftRight(Local2, 1, Local2)
+                    Increment(Local1)
+                }
+                Increment(Local0)
+            }
+            Return(One)
+        }
+    }
 }
diff --git a/src/acpi.c b/src/acpi.c
index f613b03..bedd59a 100644
--- a/src/acpi.c
+++ b/src/acpi.c
@@ -12,6 +12,8 @@
 #include "pci_ids.h" // PCI_VENDOR_ID_INTEL
 #include "pci_regs.h" // PCI_INTERRUPT_LINE
 #include "paravirt.h"
+#include "memmap.h"
+#include "types.h"
 
 /****************************************************/
 /* ACPI tables init */
@@ -344,22 +346,41 @@ build_fadt(int bdf)
     return fadt;
 }
 
+/* BIOS use only area unit: transfer MADT info to DSDT */
+#define MADT_INFO_PHYSICAL_ADDRESS    0x514
+struct madt_info {
+    u32 madt_csum_addr;    /* address of MADT checksum */
+    u32 madt_lapic0_addr;  /* address of first MADT LAPIC struct */
+    u32 maxcpus;           /* max cpus */
+};
+
 static void*
 build_madt(void)
 {
+    struct madt_info *madt_info;
+
     int madt_size = (sizeof(struct multiple_apic_table)
                      + sizeof(struct madt_processor_apic) * MaxCountCPUs
                      + sizeof(struct madt_io_apic)
                      + sizeof(struct madt_intsrcovr) * 16);
-    struct multiple_apic_table *madt = malloc_high(madt_size);
+    madt_size = ALIGN(madt_size, PAGE_SIZE);
+    struct multiple_apic_table *madt = memalign_high(PAGE_SIZE, madt_size);
     if (!madt) {
         dprintf(1, "Not enough memory for madt!\n");
         return NULL;
     }
+    add_e820((u32)madt, madt_size, E820_NVS);
     memset(madt, 0, madt_size);
     madt->local_apic_address = cpu_to_le32(BUILD_APIC_ADDR);
     madt->flags = cpu_to_le32(1);
     struct madt_processor_apic *apic = (void*)&madt[1];
+
+    madt_info = (struct madt_info *)MADT_INFO_PHYSICAL_ADDRESS;
+    memset(madt_info, 0, sizeof(*madt_info));
+    madt_info->madt_csum_addr = (u32)&madt->checksum;
+    madt_info->madt_lapic0_addr = (u32)apic;
+    madt_info->maxcpus = MaxCountCPUs;
+
     int i;
     for (i=0; i<MaxCountCPUs; i++) {
         apic->type = APIC_PROCESSOR;
@@ -406,65 +427,6 @@ build_madt(void)
     return madt;
 }
 
-#define SSDT_SIGNATURE 0x54445353 // SSDT
-static void*
-build_ssdt(void)
-{
-    int acpi_cpus = MaxCountCPUs > 0xff ? 0xff : MaxCountCPUs;
-    // calculate the length of processor block and scope block
-    // excluding PkgLength
-    int cpu_length = 13 * acpi_cpus + 4;
-
-    int length = sizeof(struct acpi_table_header) + 3 + cpu_length;
-    u8 *ssdt = malloc_high(length);
-    if (! ssdt) {
-        dprintf(1, "No space for ssdt!\n");
-        return NULL;
-    }
-
-    u8 *ssdt_ptr = ssdt;
-    ssdt_ptr[9] = 0; // checksum;
-    ssdt_ptr += sizeof(struct acpi_table_header);
-
-    // build processor scope header
-    *(ssdt_ptr++) = 0x10; // ScopeOp
-    if (cpu_length <= 0x3e) {
-        *(ssdt_ptr++) = cpu_length + 1;
-    } else {
-        *(ssdt_ptr++) = 0x7F;
-        *(ssdt_ptr++) = (cpu_length + 2) >> 6;
-    }
-    *(ssdt_ptr++) = '_'; // Name
-    *(ssdt_ptr++) = 'P';
-    *(ssdt_ptr++) = 'R';
-    *(ssdt_ptr++) = '_';
-
-    // build object for each processor
-    int i;
-    for (i=0; i<acpi_cpus; i++) {
-        *(ssdt_ptr++) = 0x5B; // ProcessorOp
-        *(ssdt_ptr++) = 0x83;
-        *(ssdt_ptr++) = 0x0B; // Length
-        *(ssdt_ptr++) = 'C';  // Name (CPUxx)
-        *(ssdt_ptr++) = 'P';
-        if ((i & 0xf0) != 0)
-            *(ssdt_ptr++) = (i >> 4) < 0xa ? (i >> 4) + '0' : (i >> 4) + 'A' - 0xa;
-        else
-            *(ssdt_ptr++) = 'U';
-        *(ssdt_ptr++) = (i & 0xf) < 0xa ? (i & 0xf) + '0' : (i & 0xf) + 'A' - 0xa;
-        *(ssdt_ptr++) = i;
-        *(ssdt_ptr++) = 0x10; // Processor block address
-        *(ssdt_ptr++) = 0xb0;
-        *(ssdt_ptr++) = 0;
-        *(ssdt_ptr++) = 0;
-        *(ssdt_ptr++) = 6;    // Processor block length
-    }
-
-    build_header((void*)ssdt, SSDT_SIGNATURE, ssdt_ptr - ssdt, 1);
-
-    return ssdt;
-}
-
 #define HPET_SIGNATURE 0x54455048 //HPET
 static void*
 build_hpet(void)
@@ -631,7 +593,6 @@ acpi_bios_init(void)
 
     // Add tables
     ACPI_INIT_TABLE(build_fadt(bdf));
-    ACPI_INIT_TABLE(build_ssdt());
     ACPI_INIT_TABLE(build_madt());
     ACPI_INIT_TABLE(build_hpet());
     ACPI_INIT_TABLE(build_srat());
-- 
1.6.5.6

