From 650fe0a90e0a7aba28f8a1e1a80643c5315ccb2c Mon Sep 17 00:00:00 2001
From: Liu, Jinsong <jinsong.liu@intel.com>
Date: Mon, 24 May 2010 19:23:24 +0800
Subject: [PATCH] KVM vcpu hotplug seabios infrastructure

This patch is to support KVM vcpu hotplug feature.
It ported from KVM bochs bios, and update some points to KVM seabios:
1. build ssdt with 15/64 processor obj, which separately support Win2000 and other oses;
2. build madt accordingly, protect it as 'E820_NVS', and keep madt checksum and lapic flag correctly when cpu hotplug;
3. define Processor under \_SB instead of \_PR, so that it works better with latest linux like 2.6.32 later;
4. for Processor _MAT method, explicitly transfer it 'ToBuffer' so that os will not confused with 'Integer' which will result in parse failure;
5. for Processor _STA method, use 0x0 instead of 0x9 for cpu hot-remove, which matchs better with ACPI 4.0 spec, and works better with latest linux;
6. add Processor _EJ0 method, so that 'eject' appear under linux /sys, and triggered by uevent to make cpu hot-remove;

Signed-off-by: Liu, Jinsong <jinosng.liu@intel.com>
---
 Makefile          |   16 ++++++-
 src/acpi-dsdt.dsl |    4 +-
 src/acpi-dsdt.hex |   45 ++++++++++----------
 src/acpi-ssdt.dsl |  116 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/acpi.c        |   89 ++++++++++++++++------------------------
 src/config.h      |    5 ++
 src/mk_ssdt.c     |   24 +++++++++++
 7 files changed, 218 insertions(+), 81 deletions(-)
 create mode 100644 src/acpi-ssdt.dsl
 create mode 100644 src/mk_ssdt.c

diff --git a/Makefile b/Makefile
index b896b54..e5bd231 100644
--- a/Makefile
+++ b/Makefile
@@ -45,7 +45,7 @@ CFLAGS16INC = $(CFLAGSSEG) -DMODE16=1 \
               $(call cc-option,$(CC),--param large-stack-frame=4,)
 CFLAGS16 = $(CFLAGS16INC) -g
 
-all: $(OUT) $(OUT)bios.bin
+all: 15.c anycpu.c $(OUT) $(OUT)bios.bin
 
 # Run with "make V=1" to see the actual compile commands
 ifdef V
@@ -194,7 +194,19 @@ src/acpi-dsdt.hex: src/acpi-dsdt.dsl
 	@echo "Compiling DSDT"
 	$(Q)cpp -P $< > $(OUT)acpi-dsdt.dsl.i
 	$(Q)iasl -tc -p $@ $(OUT)acpi-dsdt.dsl.i
-	$(Q)rm $(OUT)acpi-dsdt.dsl.i
+	$(Q)sed -i -e 's/AmlCode/acpi_dsdt/g' $@
+	$(Q)rm $(OUT)acpi-dsdt.dsl.i src/acpi-dsdt.aml
+
+####### ssdt build rules
+15.c anycpu.c: %.c: src/acpi-ssdt.dsl src/mk_ssdt.c
+	$(Q)$(CC) -o mk_$* src/mk_ssdt.c
+	head -n -2 $< > src/acpi-ssdt-$*.dsl.i
+	./mk_$* >> src/acpi-ssdt-$*.dsl.i
+	@echo "Compiling SSDT support cpus:" $*
+	$(Q)cpp -P src/acpi-ssdt-$*.dsl.i > $(OUT)acpi-ssdt-$*.dsl
+	$(Q)iasl -tc -p src/acpi-ssdt-$*.hex $(OUT)acpi-ssdt-$*.dsl
+	$(Q)sed -i -e 's/AmlCode/acpi_ssdt_$*/g' src/acpi-ssdt-$*.hex
+	$(Q)rm mk_$* src/acpi-ssdt-$*.dsl.i src/acpi-ssdt-$*.aml $(OUT)acpi-ssdt-$*.dsl
 
 ####### Generic rules
 clean:
diff --git a/src/acpi-dsdt.dsl b/src/acpi-dsdt.dsl
index cc31112..96834fa 100644
--- a/src/acpi-dsdt.dsl
+++ b/src/acpi-dsdt.dsl
@@ -700,9 +700,7 @@ DefinitionBlock (
             Return (0x01)
 
         }
-        Method(_L02) {
-            Return(0x01)
-        }
+        /* _L02 defined at ssdt for CPU notification */
         Method(_L03) {
             Return(0x01)
         }
diff --git a/src/acpi-dsdt.hex b/src/acpi-dsdt.hex
index 465e93e..e7c420a 100644
--- a/src/acpi-dsdt.hex
+++ b/src/acpi-dsdt.hex
@@ -1,22 +1,22 @@
 /*
  * 
  * Intel ACPI Component Architecture
- * ASL Optimizing Compiler version 20090123 [Feb 25 2009]
- * Copyright (C) 2000 - 2009 Intel Corporation
+ * ASL Optimizing Compiler version 20061109 [Jul 16 2007]
+ * Copyright (C) 2000 - 2006 Intel Corporation
  * Supports ACPI Specification Revision 3.0a
  * 
- * Compilation of "out/acpi-dsdt.dsl.i" - Wed Dec 30 12:30:21 2009
+ * Compilation of "out/acpi-dsdt.dsl.i" - Mon May 17 16:39:05 2010
  * 
  * C source code output
  *
  */
-unsigned char AmlCode[] =
+unsigned char acpi_dsdt[] =
 {
-    0x44,0x53,0x44,0x54,0x22,0x1E,0x00,0x00,  /* 00000000    "DSDT"..." */
-    0x01,0x71,0x42,0x58,0x50,0x43,0x00,0x00,  /* 00000008    ".qBXPC.." */
+    0x44,0x53,0x44,0x54,0x19,0x1E,0x00,0x00,  /* 00000000    "DSDT...." */
+    0x01,0x5E,0x42,0x58,0x50,0x43,0x00,0x00,  /* 00000008    ".^BXPC.." */
     0x42,0x58,0x44,0x53,0x44,0x54,0x00,0x00,  /* 00000010    "BXDSDT.." */
     0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C,  /* 00000018    "....INTL" */
-    0x23,0x01,0x09,0x20,0x10,0x1C,0x5C,0x00,  /* 00000020    "#.. ..\." */
+    0x09,0x11,0x06,0x20,0x10,0x1C,0x5C,0x00,  /* 00000020    "... ..\." */
     0x5B,0x80,0x44,0x42,0x47,0x5F,0x01,0x0B,  /* 00000028    "[.DBG_.." */
     0x44,0xB0,0x0A,0x04,0x5B,0x81,0x0B,0x44,  /* 00000030    "D...[..D" */
     0x42,0x47,0x5F,0x03,0x44,0x42,0x47,0x4C,  /* 00000038    "BG_.DBGL" */
@@ -643,7 +643,7 @@ unsigned char AmlCode[] =
     0x08,0x5F,0x53,0x34,0x5F,0x12,0x06,0x04,  /* 000013A0    "._S4_..." */
     0x00,0x00,0x00,0x00,0x08,0x5F,0x53,0x35,  /* 000013A8    "....._S5" */
     0x5F,0x12,0x06,0x04,0x00,0x00,0x00,0x00,  /* 000013B0    "_......." */
-    0x10,0x49,0xA6,0x5F,0x47,0x50,0x45,0x08,  /* 000013B8    ".I._GPE." */
+    0x10,0x40,0xA6,0x5F,0x47,0x50,0x45,0x08,  /* 000013B8    ".@._GPE." */
     0x5F,0x48,0x49,0x44,0x0D,0x41,0x43,0x50,  /* 000013C0    "_HID.ACP" */
     0x49,0x30,0x30,0x30,0x36,0x00,0x14,0x08,  /* 000013C8    "I0006..." */
     0x5F,0x4C,0x30,0x30,0x00,0xA4,0x01,0x14,  /* 000013D0    "_L00...." */
@@ -961,20 +961,19 @@ unsigned char AmlCode[] =
     0x86,0x5C,0x2F,0x03,0x5F,0x53,0x42,0x5F,  /* 00001D90    ".\/._SB_" */
     0x50,0x43,0x49,0x30,0x53,0x33,0x31,0x5F,  /* 00001D98    "PCI0S31_" */
     0x0A,0x03,0xA4,0x01,0x14,0x08,0x5F,0x4C,  /* 00001DA0    "......_L" */
-    0x30,0x32,0x00,0xA4,0x01,0x14,0x08,0x5F,  /* 00001DA8    "02....._" */
-    0x4C,0x30,0x33,0x00,0xA4,0x01,0x14,0x08,  /* 00001DB0    "L03....." */
-    0x5F,0x4C,0x30,0x34,0x00,0xA4,0x01,0x14,  /* 00001DB8    "_L04...." */
-    0x08,0x5F,0x4C,0x30,0x35,0x00,0xA4,0x01,  /* 00001DC0    "._L05..." */
-    0x14,0x08,0x5F,0x4C,0x30,0x36,0x00,0xA4,  /* 00001DC8    ".._L06.." */
-    0x01,0x14,0x08,0x5F,0x4C,0x30,0x37,0x00,  /* 00001DD0    "..._L07." */
-    0xA4,0x01,0x14,0x08,0x5F,0x4C,0x30,0x38,  /* 00001DD8    "...._L08" */
+    0x30,0x33,0x00,0xA4,0x01,0x14,0x08,0x5F,  /* 00001DA8    "03....._" */
+    0x4C,0x30,0x34,0x00,0xA4,0x01,0x14,0x08,  /* 00001DB0    "L04....." */
+    0x5F,0x4C,0x30,0x35,0x00,0xA4,0x01,0x14,  /* 00001DB8    "_L05...." */
+    0x08,0x5F,0x4C,0x30,0x36,0x00,0xA4,0x01,  /* 00001DC0    "._L06..." */
+    0x14,0x08,0x5F,0x4C,0x30,0x37,0x00,0xA4,  /* 00001DC8    ".._L07.." */
+    0x01,0x14,0x08,0x5F,0x4C,0x30,0x38,0x00,  /* 00001DD0    "..._L08." */
+    0xA4,0x01,0x14,0x08,0x5F,0x4C,0x30,0x39,  /* 00001DD8    "...._L09" */
     0x00,0xA4,0x01,0x14,0x08,0x5F,0x4C,0x30,  /* 00001DE0    "....._L0" */
-    0x39,0x00,0xA4,0x01,0x14,0x08,0x5F,0x4C,  /* 00001DE8    "9....._L" */
-    0x30,0x41,0x00,0xA4,0x01,0x14,0x08,0x5F,  /* 00001DF0    "0A....._" */
-    0x4C,0x30,0x42,0x00,0xA4,0x01,0x14,0x08,  /* 00001DF8    "L0B....." */
-    0x5F,0x4C,0x30,0x43,0x00,0xA4,0x01,0x14,  /* 00001E00    "_L0C...." */
-    0x08,0x5F,0x4C,0x30,0x44,0x00,0xA4,0x01,  /* 00001E08    "._L0D..." */
-    0x14,0x08,0x5F,0x4C,0x30,0x45,0x00,0xA4,  /* 00001E10    ".._L0E.." */
-    0x01,0x14,0x08,0x5F,0x4C,0x30,0x46,0x00,  /* 00001E18    "..._L0F." */
-    0xA4,0x01,
+    0x41,0x00,0xA4,0x01,0x14,0x08,0x5F,0x4C,  /* 00001DE8    "A....._L" */
+    0x30,0x42,0x00,0xA4,0x01,0x14,0x08,0x5F,  /* 00001DF0    "0B....._" */
+    0x4C,0x30,0x43,0x00,0xA4,0x01,0x14,0x08,  /* 00001DF8    "L0C....." */
+    0x5F,0x4C,0x30,0x44,0x00,0xA4,0x01,0x14,  /* 00001E00    "_L0D...." */
+    0x08,0x5F,0x4C,0x30,0x45,0x00,0xA4,0x01,  /* 00001E08    "._L0E..." */
+    0x14,0x08,0x5F,0x4C,0x30,0x46,0x00,0xA4,  /* 00001E10    ".._L0F.." */
+    0x01,
 };
diff --git a/src/acpi-ssdt.dsl b/src/acpi-ssdt.dsl
new file mode 100644
index 0000000..9084c7a
--- /dev/null
+++ b/src/acpi-ssdt.dsl
@@ -0,0 +1,116 @@
+/*
+ * Bochs/QEMU ACPI SSDT ASL definition
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+DefinitionBlock (
+    "acpi-ssdt.aml",    // Output Filename
+    "SSDT",             // Signature
+    0x01,               // SSDT Compliance Revision
+    "BXPC",             // OEMID
+    "BXSSDT",           // TABLE ID
+    0x1                 // OEM Revision
+    )
+{
+    Scope (\_GPE)
+    {
+        /*
+         * _L02 method for CPU notification
+         */
+        Method(_L02) {
+            Return(\_SB.PRSC())
+        }
+    }
+
+
+    Scope (\_SB)
+    {
+        /* 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 */
+        }
+
+        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(0x0) }                 \
+            }                                                                 \
+            Method (_EJ0, 1, NotSerialized) {                                 \
+                Sleep (0xC8)                                                  \
+            }                                                                 \
+        }                                                                     \
+
+        #define gen_ntfy(nr)                        \
+        If (LEqual(Arg0, 0x##nr)) {                 \
+            If (LNotEqual(Arg1, \_SB.C##nr.FLG)) {  \
+                Store (Arg1, \_SB.C##nr.FLG)        \
+                If (LEqual(Arg1, 1)) {              \
+                    Notify(C##nr, 1)                \
+                    Subtract(\_SB.MSU, 1, \_SB.MSU) \
+                } Else {                            \
+                    Notify(C##nr, 3)                \
+                    Add(\_SB.MSU, 1, \_SB.MSU)      \
+                }                                   \
+            }                                       \
+        }
+
+        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)) {
+                                NTFY(Add(Multiply(Local0, 8), Local1),
+                                                And(Local2, 1))
+                                ShiftRight(Local2, 1, Local2)
+                                Increment(Local1)
+                        }
+                        Increment(Local0)
+                }
+                Return(One)
+        }
+    }
+}
diff --git a/src/acpi.c b/src/acpi.c
index 0559443..976206c 100644
--- a/src/acpi.c
+++ b/src/acpi.c
@@ -12,6 +12,9 @@
 #include "pci_ids.h" // PCI_VENDOR_ID_INTEL
 #include "pci_regs.h" // PCI_INTERRUPT_LINE
 #include "paravirt.h"
+#include "memmap.h"
+#include "types.h"
+#include "config.h"
 
 /****************************************************/
 /* ACPI tables init */
@@ -269,6 +272,8 @@ struct srat_memory_affinity
 } PACKED;
 
 #include "acpi-dsdt.hex"
+#include "acpi-ssdt-15.hex"
+#include "acpi-ssdt-anycpu.hex"
 
 static inline u16 cpu_to_le16(u16 x)
 {
@@ -300,7 +305,7 @@ build_fadt(int bdf)
 {
     struct fadt_descriptor_rev1 *fadt = malloc_high(sizeof(*fadt));
     struct facs_descriptor_rev1 *facs = memalign_high(64, sizeof(*facs));
-    void *dsdt = malloc_high(sizeof(AmlCode));
+    void *dsdt = malloc_high(sizeof(acpi_dsdt));
 
     if (!fadt || !facs || !dsdt) {
         warn_noalloc();
@@ -313,7 +318,7 @@ build_fadt(int bdf)
     facs->length = cpu_to_le32(sizeof(*facs));
 
     /* DSDT */
-    memcpy(dsdt, AmlCode, sizeof(AmlCode));
+    memcpy(dsdt, acpi_dsdt, sizeof(acpi_dsdt));
 
     /* FADT */
     memset(fadt, 0, sizeof(*fadt));
@@ -344,24 +349,42 @@ 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 */
+};
+
 static void*
 build_madt(void)
 {
+    struct madt_info *madt_info;
+    int lapic_num = MaxCountCPUs > 15 ? MAX_CPU_GENEOS : MAX_CPU_WIN2000;
+
     int madt_size = (sizeof(struct multiple_apic_table)
-                     + sizeof(struct madt_processor_apic) * MaxCountCPUs
+                     + sizeof(struct madt_processor_apic) * lapic_num
                      + 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) {
         warn_noalloc();
         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;
+
     int i;
-    for (i=0; i<MaxCountCPUs; i++) {
+    for (i=0; i<lapic_num; i++) {
         apic->type = APIC_PROCESSOR;
         apic->length = sizeof(*apic);
         apic->processor_id = i;
@@ -406,63 +429,23 @@ 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;
+    void *ssdt = malloc_high(MaxCountCPUs > 15 ?
+                             sizeof(acpi_ssdt_anycpu) :
+                             sizeof(acpi_ssdt_15));
 
-    int length = sizeof(struct acpi_table_header) + 3 + cpu_length;
-    u8 *ssdt = malloc_high(length);
     if (! ssdt) {
         warn_noalloc();
         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) {
-        /* Handle 1-4 CPUs with one byte encoding */
-        *(ssdt_ptr++) = cpu_length + 1;
-    } else {
-        /* Handle 5-314 CPUs with two byte encoding */
-        *(ssdt_ptr++) = 0x40 | ((cpu_length + 2) & 0xf);
-        *(ssdt_ptr++) = (cpu_length + 2) >> 4;
-    }
-    *(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);
+    /* SSDT */
+    if (MaxCountCPUs > 15)
+        memcpy(ssdt, acpi_ssdt_anycpu, sizeof(acpi_ssdt_anycpu));
+    else
+        memcpy(ssdt, acpi_ssdt_15, sizeof(acpi_ssdt_15));
 
     return ssdt;
 }
diff --git a/src/config.h b/src/config.h
index 1362581..c486dbf 100644
--- a/src/config.h
+++ b/src/config.h
@@ -204,4 +204,9 @@
 #define DEBUG_invalid 3
 #define DEBUG_thread 2
 
+/* Windows 2000 support max cpus to 15, otherwise will result in BSOD */
+/* Other os support more cpus, we define here support max cpus to 64 */
+#define MAX_CPU_WIN2000 15
+#define MAX_CPU_GENEOS  64
+
 #endif // config.h
diff --git a/src/mk_ssdt.c b/src/mk_ssdt.c
new file mode 100644
index 0000000..e104dca
--- /dev/null
+++ b/src/mk_ssdt.c
@@ -0,0 +1,24 @@
+#include <stdio.h>
+#include "config.h"
+
+int main(int argc, char **argv)
+{
+    unsigned int i, max_cpus = MAX_CPU_GENEOS;
+
+    sscanf(argv[0], "%*[^0-9]%u", &max_cpus);
+
+    printf("\n");
+    for (i = 0; i < max_cpus; i++)
+        printf("        gen_processor(%d, %x)\n", i, i);
+
+    printf("\n");
+    printf("        Method (NTFY, 2) {\n");
+    for (i = 0; i < max_cpus; i++)
+        printf("        gen_ntfy(%x)\n", i);
+    printf("        Return(One)\n");
+    printf("        }\n");
+    printf("    }\n");
+    printf("}\n");
+
+    return 0;
+}
-- 
1.6.5.6

