[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[win-pv-devel] [PATCH v2] Map Local APIC IDs to Processor IDs through the MADT



To use the FIFO EVTCHN ABI the frontend code needs to know the vcpu id of
the guest CPUs. This mapping is currently done by taking the the CPU local
APIC ID and dividing by 2. This currently works on most Xen installations
but Matt Wilson advises that this will not work on AWS.
This patch introduces code to map and parse the ACPI RSDP, XSDT and MADT
(APIC) tables such that the local APIC substructures present in the latter
can be used to map local APIC ID to processor ID (which is identical to
vcpu id).

Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
Cc: Matt Wilson <msw@xxxxxxxxx>
---
v2:
 - Add missing line into vs2013 vcxproj

 src/xen/acpi.c         | 313 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/xen/acpi.h         | 108 +++++++++++++++++
 src/xen/driver.c       |  28 +++--
 src/xen/system.c       | 117 +++++++++++++++++-
 vs2012/xen/xen.vcxproj |   1 +
 vs2013/xen/xen.vcxproj |   1 +
 6 files changed, 556 insertions(+), 12 deletions(-)
 create mode 100644 src/xen/acpi.c
 create mode 100644 src/xen/acpi.h

diff --git a/src/xen/acpi.c b/src/xen/acpi.c
new file mode 100644
index 0000000..124dcb6
--- /dev/null
+++ b/src/xen/acpi.c
@@ -0,0 +1,313 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, 
+ * with or without modification, are permitted provided 
+ * that the following conditions are met:
+ * 
+ * *   Redistributions of source code must retain the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer in the documentation and/or other 
+ *     materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE.
+ */
+
+#include <ntddk.h>
+#include <stdarg.h>
+#include <xen.h>
+#include <util.h>
+
+#include "acpi.h"
+#include "dbg_print.h"
+#include "assert.h"
+
+#define XENBUS_ACPI_TAG 'IPCA'
+
+static ACPI_RSDP    AcpiRsdp;
+static PACPI_XSDT   AcpiXsdt;
+
+static FORCEINLINE PVOID
+__AcpiAllocate(
+    IN  ULONG   Length
+    )
+{
+    return __AllocatePoolWithTag(NonPagedPool, Length, XENBUS_ACPI_TAG);
+}
+
+static FORCEINLINE VOID
+__AcpiFree(
+    IN  PVOID   Buffer
+    )
+{
+    ExFreePoolWithTag(Buffer, XENBUS_ACPI_TAG);
+}
+
+static BOOLEAN
+AcpiVerifyChecksum(
+    IN  PVOID   Table,
+    IN  ULONG   Length
+    )
+{
+    UCHAR       Sum;
+    ULONG       Index;
+
+    Sum = 0;
+    for (Index = 0; Index < Length; Index++)
+        Sum += ((PUCHAR)Table)[Index];
+
+    return (Sum == 0) ? TRUE : FALSE;
+}
+
+static NTSTATUS
+AcpiFindRsdp(
+    VOID
+    )
+{
+    PHYSICAL_ADDRESS    Start;
+    PHYSICAL_ADDRESS    End;
+    ULONG               Length;
+    PUCHAR              Data;
+    ULONG               Offset;
+    PACPI_RSDP          Rsdp;
+    NTSTATUS            status;
+
+    Trace("====>\n");
+
+    if (strncmp(AcpiRsdp.Signature,
+                "RSD PTR ",
+                sizeof (AcpiRsdp.Signature)) == 0)
+        goto done;
+
+    Start.QuadPart = 0xE0000;
+    End.QuadPart = 0xFFFFF;
+
+    Length = (ULONG)(End.QuadPart + 1 - Start.QuadPart);
+
+    Data = MmMapIoSpace(Start, Length, MmCached);
+
+    status = STATUS_UNSUCCESSFUL;
+    if (Data == NULL)
+        goto fail1;
+
+    for (Offset = 0;
+         Offset + sizeof (ACPI_RSDP) < Length;
+         Offset += 16) {
+        Rsdp = (PACPI_RSDP)(Data + Offset);
+
+        if (strncmp(Rsdp->Signature,
+                    "RSD PTR ",
+                    sizeof (Rsdp->Signature)) == 0 &&
+            AcpiVerifyChecksum(Rsdp, sizeof (ACPI_RSDP)))
+            goto found;
+    }
+
+    status = STATUS_UNSUCCESSFUL;
+    goto fail2;
+
+found:
+    Info("0x%p\n", Start.QuadPart + Offset);
+
+    // Copy the table for reference
+    AcpiRsdp = *Rsdp;
+
+    MmUnmapIoSpace(Data, Length);
+
+done:
+    Trace("<====\n");
+
+    return STATUS_SUCCESS;
+
+fail2:
+    Error("fail2\n");
+
+    MmUnmapIoSpace(Data, Length);
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+static NTSTATUS
+AcpiGetXsdt(
+    VOID
+    )
+{
+    PHYSICAL_ADDRESS    Address;
+    PACPI_XSDT          Xsdt;
+    NTSTATUS            status;
+
+    Trace("====>\n");
+
+    if (AcpiXsdt != NULL)
+        goto done;
+
+    Address.QuadPart = AcpiRsdp.XsdtAddress;
+
+    Info("0x%p\n", Address.QuadPart);
+
+    Xsdt = MmMapIoSpace(Address, PAGE_SIZE, MmCached);
+
+    status = STATUS_UNSUCCESSFUL;
+    if (Xsdt == NULL)
+        goto fail1;
+
+    if (strncmp(Xsdt->Header.Signature,
+                "XSDT",
+                sizeof (Xsdt->Header.Signature)) != 0)
+        goto fail2;
+
+    if (!AcpiVerifyChecksum(Xsdt, Xsdt->Header.Length))
+        goto fail3;
+
+    AcpiXsdt = __AcpiAllocate(Xsdt->Header.Length);
+
+    status = STATUS_NO_MEMORY;
+    if (AcpiXsdt == NULL)
+        goto fail4;
+
+    RtlCopyMemory(AcpiXsdt, Xsdt, Xsdt->Header.Length);
+
+    MmUnmapIoSpace(Xsdt, PAGE_SIZE);
+
+done:
+    Trace("<====\n");
+
+    return STATUS_SUCCESS;
+
+fail4:
+    Error("fail4\n");
+
+fail3:
+    Error("fail3\n");
+
+fail2:
+    Error("fail2\n");
+
+    MmUnmapIoSpace(Xsdt, PAGE_SIZE);
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+NTSTATUS
+AcpiGetTable(
+    IN      const CHAR  *Signature,
+    OUT     PVOID       Buffer OPTIONAL,
+    IN OUT  PULONG      Length
+    )
+{
+    ULONG               Count;
+    ULONG               Index;
+    PACPI_HEADER        Header;
+    NTSTATUS            status;
+
+    status = AcpiGetXsdt();
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    Count = (AcpiXsdt->Header.Length - FIELD_OFFSET(ACPI_XSDT, Entry)) /
+            sizeof (ULONG64);
+
+    for (Index = 0; Index < Count; Index++) {
+        PHYSICAL_ADDRESS    Address;
+
+        Address.QuadPart = AcpiXsdt->Entry[Index];
+
+        Header = MmMapIoSpace(Address, PAGE_SIZE, MmCached);
+
+        status = STATUS_UNSUCCESSFUL;
+        if (Header == NULL)
+            goto fail2;
+
+        if (strncmp(Header->Signature,
+                    Signature,
+                    sizeof (Header->Signature)) == 0 &&
+            AcpiVerifyChecksum(Header, Header->Length))
+            goto found;
+
+        MmUnmapIoSpace(Header, PAGE_SIZE);
+    }
+
+    status = STATUS_UNSUCCESSFUL;
+    goto fail3;
+
+found:
+    status = STATUS_BUFFER_OVERFLOW;
+    if (Buffer == NULL || Header->Length > *Length) {
+        *Length = Header->Length;
+        goto fail4;
+    }
+
+    RtlCopyMemory(Buffer, Header, Header->Length);
+
+    MmUnmapIoSpace(Header, PAGE_SIZE);
+
+    return STATUS_SUCCESS;
+
+fail4:
+    MmUnmapIoSpace(Header, PAGE_SIZE);
+
+fail3:
+    if (status != STATUS_BUFFER_OVERFLOW)
+        Error("fail3\n");
+
+fail2:
+    if (status != STATUS_BUFFER_OVERFLOW)
+        Error("fail2\n");
+
+fail1:
+    if (status != STATUS_BUFFER_OVERFLOW)
+        Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+NTSTATUS
+AcpiInitialize(
+    VOID
+    )
+{
+    NTSTATUS    status;
+
+    status = AcpiFindRsdp();
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+VOID
+AcpiTeardown(
+    VOID
+    )
+{
+    if (AcpiXsdt != NULL) {
+        __AcpiFree(AcpiXsdt);
+        AcpiXsdt = NULL;
+    }
+}
diff --git a/src/xen/acpi.h b/src/xen/acpi.h
new file mode 100644
index 0000000..334f62a
--- /dev/null
+++ b/src/xen/acpi.h
@@ -0,0 +1,108 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, 
+ * with or without modification, are permitted provided 
+ * that the following conditions are met:
+ * 
+ * *   Redistributions of source code must retain the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer in the documentation and/or other 
+ *     materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE.
+ */
+
+#ifndef _XEN_ACPI_H
+#define _XEN_ACPI_H
+
+#include <ntddk.h>
+
+#pragma pack(push, 1)
+
+typedef struct _ACPI_RSDP {
+    CHAR    Signature[8];
+    UCHAR   Checksum;
+    CHAR    OemID[6];
+    UCHAR   Revision;
+    ULONG   RsdtAddress;
+    ULONG   Length;
+    ULONG64 XsdtAddress;
+    UCHAR   ExtendedChecksum;
+    UCHAR   Reserved[3];
+} ACPI_RSDP, *PACPI_RSDP;
+
+typedef struct _ACPI_HEADER {
+    CHAR    Signature[4];
+    ULONG   Length;
+    UCHAR   Revision;
+    UCHAR   Checksum;
+    CHAR    OemID[6];
+    CHAR    OemTableID[8];
+    ULONG   OemRevision;
+    CHAR    CreatorID[4];
+    ULONG   CreatorRevision;
+} ACPI_HEADER, *PACPI_HEADER;
+
+typedef struct _ACPI_XSDT {
+    ACPI_HEADER Header;
+    ULONG64     Entry[1];
+} ACPI_XSDT, *PACPI_XSDT;
+
+typedef struct _ACPI_MADT {
+    ACPI_HEADER Header;
+    ULONG       LocalAPICAddress;
+    ULONG       Flags;
+} ACPI_MADT, *PACPI_MADT;
+
+typedef struct _ACPI_MADT_HEADER {
+    UCHAR   Type;
+    UCHAR   Length;
+} ACPI_MADT_HEADER, *PACPI_MADT_HEADER;
+
+#define ACPI_MADT_TYPE_LOCAL_APIC   0x00
+
+typedef struct _ACPI_MADT_LOCAL_APIC {
+    ACPI_MADT_HEADER    Header;
+    UCHAR               ProcessorID;
+    UCHAR               ApicID;
+    ULONG               Flags;
+} ACPI_MADT_LOCAL_APIC, *PACPI_MADT_LOCAL_APIC;
+
+#pragma pack(pop)
+
+extern NTSTATUS
+AcpiInitialize(
+    VOID
+    );
+
+extern NTSTATUS
+AcpiGetTable(
+    IN      const CHAR  *Signature,
+    OUT     PVOID       Buffer OPTIONAL,
+    IN OUT  PULONG      Length
+    );
+
+extern VOID
+AcpiTeardown(
+    VOID
+    );
+
+#endif  // _XEN_ACPI_H
+
diff --git a/src/xen/driver.c b/src/xen/driver.c
index fce75aa..a4e91aa 100644
--- a/src/xen/driver.c
+++ b/src/xen/driver.c
@@ -39,6 +39,7 @@
 #include "module.h"
 #include "process.h"
 #include "system.h"
+#include "acpi.h"
 #include "bug_check.h"
 #include "dbg_print.h"
 #include "assert.h"
@@ -143,50 +144,59 @@ DllInitialize(
          MONTH,
          YEAR);
 
-    status = SystemInitialize();
+    status = AcpiInitialize();
     if (!NT_SUCCESS(status))
         goto fail2;
 
-    status = HypercallInitialize();
+    status = SystemInitialize();
     if (!NT_SUCCESS(status))
         goto fail3;
 
-    status = BugCheckInitialize();
+    status = HypercallInitialize();
     if (!NT_SUCCESS(status))
         goto fail4;
 
-    status = ModuleInitialize();
+    status = BugCheckInitialize();
     if (!NT_SUCCESS(status))
         goto fail5;
 
-    status = ProcessInitialize();
+    status = ModuleInitialize();
     if (!NT_SUCCESS(status))
         goto fail6;
 
+    status = ProcessInitialize();
+    if (!NT_SUCCESS(status))
+        goto fail7;
+
 done:
     Trace("<====\n");
 
     return STATUS_SUCCESS;
 
+fail7:
+    Error("fail7\n");
+
+    ModuleTeardown();
+
 fail6:
     Error("fail6\n");
 
-    ModuleTeardown();
+    BugCheckTeardown();
 
 fail5:
     Error("fail5\n");
 
-    BugCheckTeardown();
+    HypercallTeardown();
 
 fail4:
     Error("fail4\n");
 
-    HypercallTeardown();
+    SystemTeardown();
 
 fail3:
     Error("fail3\n");
 
-    SystemTeardown();
+    AcpiTeardown();
 
 fail2:
     Error("fail2\n");
diff --git a/src/xen/system.c b/src/xen/system.c
index 1ac8123..0934ac8 100644
--- a/src/xen/system.c
+++ b/src/xen/system.c
@@ -40,23 +40,44 @@
 
 #include "registry.h"
 #include "system.h"
+#include "acpi.h"
 #include "dbg_print.h"
 #include "assert.h"
 
+#define XEN_SYSTEM_TAG  'TSYS'
+
 typedef struct _SYSTEM_CPU {
     ULONG   Index;
     CHAR    Manufacturer[13];
     UCHAR   ApicID;
+    UCHAR   ProcessorID;
 } SYSTEM_CPU, *PSYSTEM_CPU;
 
 typedef struct _SYSTEM_CONTEXT {
     LONG        References;
+    PACPI_MADT  Madt;
     SYSTEM_CPU  Cpu[MAXIMUM_PROCESSORS];
     PVOID       Handle;
 } SYSTEM_CONTEXT, *PSYSTEM_CONTEXT;
 
 static SYSTEM_CONTEXT   SystemContext;
 
+static FORCEINLINE PVOID
+__SystemAllocate(
+    IN  ULONG   Length
+    )
+{
+    return __AllocatePoolWithTag(NonPagedPool, Length, XEN_SYSTEM_TAG);
+}
+
+static FORCEINLINE VOID
+__SystemFree(
+    IN  PVOID   Buffer
+    )
+{
+    ExFreePoolWithTag(Buffer, XEN_SYSTEM_TAG);
+}
+
 static FORCEINLINE const CHAR *
 __PlatformIdName(
     IN  ULONG   PlatformId
@@ -233,6 +254,77 @@ fail1:
     return status;
 }
 
+static NTSTATUS
+SystemGetAcpiInformation(
+    VOID
+    )
+{
+    PSYSTEM_CONTEXT Context = &SystemContext;
+    ULONG           Length;
+    NTSTATUS        status;
+
+    status = AcpiGetTable("APIC", NULL, &Length);
+    if (status != STATUS_BUFFER_OVERFLOW)
+        goto fail1;
+
+    Context->Madt = __SystemAllocate(Length);
+
+    status = STATUS_NO_MEMORY;
+    if (Context->Madt == NULL)
+        goto fail2;
+
+    status = AcpiGetTable("APIC", Context->Madt, &Length);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    return STATUS_SUCCESS;
+
+fail3:
+    Error("fail3\n");
+
+fail2:
+    Error("fail2\n");
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+#pragma warning(push)
+#pragma warning(disable:4715)
+
+static UCHAR
+SystemApicIDToProcessorID(
+    IN  UCHAR   ApicID
+    )
+{
+    PSYSTEM_CONTEXT Context = &SystemContext;
+    PACPI_MADT      Madt = Context->Madt;
+    ULONG           Offset;
+
+    Offset = sizeof (ACPI_MADT);
+    while (Offset < Madt->Header.Length) {
+        PACPI_MADT_HEADER       Header;
+        PACPI_MADT_LOCAL_APIC   Apic;
+
+        Header = (PACPI_MADT_HEADER)((PUCHAR)Madt + Offset);
+        Offset += Header->Length;
+
+        if (Header->Type != ACPI_MADT_TYPE_LOCAL_APIC)
+            continue;
+
+        Apic = CONTAINING_RECORD(Header, ACPI_MADT_LOCAL_APIC, Header);
+
+        if (Apic->ApicID == ApicID)
+            return Apic->ProcessorID;
+    }
+
+    BUG(__FUNCTION__);
+}
+
+#pragma warning(pop)
+
 KDEFERRED_ROUTINE   SystemCpuInformation;
 
 VOID
@@ -272,7 +364,11 @@ SystemCpuInformation(
 
     Cpu->ApicID = EBX >> 24;
 
-    Info("Local APIC ID: %02X\n", Cpu->ApicID);
+    Info("APIC ID: %02X\n", Cpu->ApicID);
+
+    Cpu->ProcessorID = SystemApicIDToProcessorID(Cpu->ApicID);
+
+    Info("PROCESSOR ID: %02X\n", Cpu->ProcessorID);
 
     Info("<==== (%u)\n", Cpu->Index);
 
@@ -476,6 +572,10 @@ SystemInitialize(
     if (!NT_SUCCESS(status))
         goto fail4;
 
+    status = SystemGetAcpiInformation();
+    if (!NT_SUCCESS(status))
+        goto fail5;
+
     SystemGetCpuInformation();
 
     status = SystemRegisterCallback(L"\\Callback\\PowerState",
@@ -483,10 +583,16 @@ SystemInitialize(
                                     NULL,
                                     &Context->Handle);
     if (!NT_SUCCESS(status))
-        goto fail5;
+        goto fail6;
 
     return STATUS_SUCCESS;
 
+fail6:
+    Error("fail6\n");
+
+    __SystemFree(Context->Madt);
+    Context->Madt = NULL;
+
 fail5:
     Error("fail5\n");
 
@@ -502,6 +608,8 @@ fail2:
 fail1:
     Error("fail1 (%08x)\n", status);
 
+    (VOID) InterlockedDecrement(&Context->References);
+
     return status;
 }
 
@@ -516,7 +624,7 @@ SystemVirtualCpuIndex(
 
     ASSERT3U(Index, <, MAXIMUM_PROCESSORS);
 
-    return Cpu->ApicID / 2;
+    return Cpu->ProcessorID;
 }
 
 VOID
@@ -531,6 +639,9 @@ SystemTeardown(
 
     RtlZeroMemory(Context->Cpu, sizeof (SYSTEM_CPU) * MAXIMUM_PROCESSORS);
 
+    __SystemFree(Context->Madt);
+    Context->Madt = NULL;
+
     (VOID) InterlockedDecrement(&Context->References);
 
     ASSERT(IsZeroMemory(Context, sizeof (SYSTEM_CONTEXT)));
diff --git a/vs2012/xen/xen.vcxproj b/vs2012/xen/xen.vcxproj
index 2f4d958..9efeaf1 100644
--- a/vs2012/xen/xen.vcxproj
+++ b/vs2012/xen/xen.vcxproj
@@ -96,6 +96,7 @@
                <ClCompile Include="..\..\src\xen\bug_check.c" />
                <ClCompile Include="..\..\src\xen\module.c" />
                <ClCompile Include="..\..\src\xen\process.c" />
+               <ClCompile Include="..\..\src\xen\acpi.c" />
                <ClCompile Include="..\..\src\xen\system.c" />
        </ItemGroup>
        <ItemGroup>
diff --git a/vs2013/xen/xen.vcxproj b/vs2013/xen/xen.vcxproj
index 81d50ea..7a09960 100644
--- a/vs2013/xen/xen.vcxproj
+++ b/vs2013/xen/xen.vcxproj
@@ -136,6 +136,7 @@
     <ClCompile Include="..\..\src\xen\bug_check.c" />
     <ClCompile Include="..\..\src\xen\module.c" />
     <ClCompile Include="..\..\src\xen\process.c" />
+    <ClCompile Include="..\..\src\xen\acpi.c" />
     <ClCompile Include="..\..\src\xen\system.c" />
   </ItemGroup>
   <ItemGroup>
-- 
2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.