aboutsummaryrefslogtreecommitdiffstats
path: root/tools/firmware
diff options
context:
space:
mode:
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2005-09-20 09:02:43 +0000
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2005-09-20 09:02:43 +0000
commit8ad67b4949d5df99c8cdecb0619990ce73e6700d (patch)
tree917f6a8675e41ac4c2dfb06c675e1c8fd9838267 /tools/firmware
parente02527cc82e38280b04f7c6a2c42effd8cdb4e62 (diff)
downloadxen-8ad67b4949d5df99c8cdecb0619990ce73e6700d.tar.gz
xen-8ad67b4949d5df99c8cdecb0619990ce73e6700d.tar.bz2
xen-8ad67b4949d5df99c8cdecb0619990ce73e6700d.zip
Dynamically generate the local apic entries in ACPI MADT table.
The number of local apic entries is decided by the #vcpus passed from the config file (eg./etc/xen/xmexample.vmx). This feature is required by the SMP VMX domain. Signed-off-by: Ke Yu <ke.yu@intel.com> Signed-off-by: Xin Li <xin.b.li@intel.com> Signed-off-by: Asit Mallick <asit.k.mallick@intel.com>
Diffstat (limited to 'tools/firmware')
-rw-r--r--tools/firmware/acpi/acpi_madt.c53
-rw-r--r--tools/firmware/acpi/acpi_madt.h6
-rw-r--r--tools/firmware/vmxassist/Makefile6
-rw-r--r--tools/firmware/vmxassist/acpi_madt.c145
-rw-r--r--tools/firmware/vmxassist/vmxloader.c6
5 files changed, 171 insertions, 45 deletions
diff --git a/tools/firmware/acpi/acpi_madt.c b/tools/firmware/acpi/acpi_madt.c
index c5f47f5995..7a0234f1f7 100644
--- a/tools/firmware/acpi/acpi_madt.c
+++ b/tools/firmware/acpi/acpi_madt.c
@@ -37,44 +37,7 @@ ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE Madt = {
ACPI_LOCAL_APIC_ADDRESS,
ACPI_MULTIPLE_APIC_FLAGS,
},
- //
- // LOCAL APIC Entries for 4 processors.
- //
- {
- {
- ACPI_PROCESSOR_LOCAL_APIC,
- sizeof (ACPI_LOCAL_APIC_STRUCTURE),
- 0x00,
- 0x00,
- 0x00000001,
- },
-
- {
- ACPI_PROCESSOR_LOCAL_APIC,
- sizeof (ACPI_LOCAL_APIC_STRUCTURE),
- 0x01,
- 0x00,
- 0x00000000
- },
-
- {
- ACPI_PROCESSOR_LOCAL_APIC,
- sizeof (ACPI_LOCAL_APIC_STRUCTURE),
- 0x02,
- 0x00,
- 0x00000000
- },
-
- {
- ACPI_PROCESSOR_LOCAL_APIC,
- sizeof (ACPI_LOCAL_APIC_STRUCTURE),
- 0x03,
- 0x00,
- 0x00000000
- }
- }
- ,
-
+
//
// IO APIC
//
@@ -87,5 +50,19 @@ ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE Madt = {
ACPI_IO_APIC_ADDRESS_1,
0x0000
}
+ },
+
+ //
+ // LOCAL APIC Entries for up to 32 processors.
+ //
+ {
+ {
+ ACPI_PROCESSOR_LOCAL_APIC,
+ sizeof (ACPI_LOCAL_APIC_STRUCTURE),
+ 0x00,
+ 0x00,
+ 0x00000001,
+ }
+
}
};
diff --git a/tools/firmware/acpi/acpi_madt.h b/tools/firmware/acpi/acpi_madt.h
index 9ee63a9368..042d3ff1a2 100644
--- a/tools/firmware/acpi/acpi_madt.h
+++ b/tools/firmware/acpi/acpi_madt.h
@@ -35,9 +35,9 @@
//
#pragma pack (1)
typedef struct {
- ACPI_2_0_MADT Header;
- ACPI_LOCAL_APIC_STRUCTURE LocalApic[4];
- ACPI_IO_APIC_STRUCTURE IoApic[1];
+ ACPI_2_0_MADT Header;
+ ACPI_IO_APIC_STRUCTURE IoApic[1];
+ ACPI_LOCAL_APIC_STRUCTURE LocalApic[32];
} ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE;
#pragma pack ()
diff --git a/tools/firmware/vmxassist/Makefile b/tools/firmware/vmxassist/Makefile
index 3c2ee4bb61..c6190ec7c6 100644
--- a/tools/firmware/vmxassist/Makefile
+++ b/tools/firmware/vmxassist/Makefile
@@ -41,9 +41,9 @@ OBJECTS = head.o trap.o vm86.o setup.o util.o
all: vmxloader
-vmxloader: roms.h vmxloader.c acpi.h
- ${CC} ${CFLAGS} ${DEFINES} -c vmxloader.c
- $(CC) -o vmxloader.tmp -m32 -nostdlib -Wl,-N -Wl,-Ttext -Wl,0x100000 vmxloader.o
+vmxloader: roms.h vmxloader.c acpi.h acpi_madt.c
+ ${CC} ${CFLAGS} ${DEFINES} -c vmxloader.c -c acpi_madt.c
+ $(CC) -o vmxloader.tmp -m32 -nostdlib -Wl,-N -Wl,-Ttext -Wl,0x100000 vmxloader.o acpi_madt.o
objcopy --change-addresses=0xC0000000 vmxloader.tmp vmxloader
rm -f vmxloader.tmp
diff --git a/tools/firmware/vmxassist/acpi_madt.c b/tools/firmware/vmxassist/acpi_madt.c
new file mode 100644
index 0000000000..aaa6025c4e
--- /dev/null
+++ b/tools/firmware/vmxassist/acpi_madt.c
@@ -0,0 +1,145 @@
+/*
+ * acpi_madt.c: Update ACPI MADT table for multiple processor guest.
+ *
+ * Yu Ke, ke.yu@intel.com
+ * Copyright (c) 2005, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "../acpi/acpi2_0.h"
+#include "../acpi/acpi_madt.h"
+
+#define NULL ((void*)0)
+
+extern int puts(const char *s);
+
+#define VCPU_MAGIC 0x76637075 /* "vcpu" */
+
+/* xc_vmx_builder wrote vcpu block at 0x9F800. Return it. */
+static int
+get_vcpus(void)
+{
+ unsigned long *vcpus;
+
+ vcpus = (unsigned long *)0x9F800;
+ if (vcpus[0] != VCPU_MAGIC) {
+ puts("Bad vcpus magic, set vcpu number=1\n");
+ return 1;
+ }
+
+ return vcpus[1];
+}
+
+static void *
+acpi_madt_get_madt(unsigned char *acpi_start)
+{
+ ACPI_2_0_RSDP *rsdp=NULL;
+ ACPI_2_0_RSDT *rsdt=NULL;
+ ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE *madt;
+
+ rsdp = (ACPI_2_0_RSDP *)(acpi_start + sizeof(ACPI_2_0_FACS));
+ if (rsdp->Signature != ACPI_2_0_RSDP_SIGNATURE) {
+ puts("Bad RSDP signature\n");
+ return NULL;
+ }
+
+ rsdt= (ACPI_2_0_RSDT *)
+ (acpi_start + rsdp->RsdtAddress - ACPI_PHYSICAL_ADDRESS);
+ if (rsdt->Header.Signature != ACPI_2_0_RSDT_SIGNATURE) {
+ puts("Bad RSDT signature\n");
+ return NULL;
+ }
+
+ madt = (ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE *)
+ ( acpi_start+ rsdt->Entry[1] - ACPI_PHYSICAL_ADDRESS);
+ if (madt->Header.Header.Signature !=
+ ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE) {
+ puts("Bad MADT signature \n");
+ return NULL;
+ }
+
+ return madt;
+}
+
+static void
+set_checksum(void *start, int checksum_offset, int len)
+{
+ unsigned char sum = 0;
+ unsigned char *ptr;
+
+ ptr = start;
+ ptr[checksum_offset] = 0;
+ while (len--)
+ sum += *ptr++;
+
+ ptr = start;
+ ptr[checksum_offset] = -sum;
+}
+
+static int
+acpi_madt_set_local_apics(
+ int nr_vcpu,
+ ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE *madt)
+{
+ int i;
+
+ if ((nr_vcpu > MAX_VIRT_CPUS) || (nr_vcpu < 0) || !madt)
+ return -1;
+
+ for (i = 0; i < nr_vcpu; i++) {
+ madt->LocalApic[i].Type = ACPI_PROCESSOR_LOCAL_APIC;
+ madt->LocalApic[i].Length = sizeof (ACPI_LOCAL_APIC_STRUCTURE);
+ madt->LocalApic[i].AcpiProcessorId = i;
+ madt->LocalApic[i].ApicId = i;
+ madt->LocalApic[i].Flags = 1;
+ }
+
+ madt->Header.Header.Length =
+ sizeof(ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE) -
+ (MAX_VIRT_CPUS - nr_vcpu)* sizeof(ACPI_LOCAL_APIC_STRUCTURE);
+
+ return 0;
+}
+
+#define FIELD_OFFSET(TYPE,Field) ((unsigned int)(&(((TYPE *) 0)->Field)))
+
+int acpi_madt_update(unsigned char *acpi_start)
+{
+ int rc;
+ ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE *madt;
+
+ madt = acpi_madt_get_madt(acpi_start);
+ if (!madt)
+ return -1;
+
+ rc = acpi_madt_set_local_apics(get_vcpus(), madt);
+ if (rc != 0)
+ return rc;
+
+ set_checksum(
+ madt, FIELD_OFFSET(ACPI_TABLE_HEADER, Checksum),
+ madt->Header.Header.Length);
+
+ return 0;
+}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/tools/firmware/vmxassist/vmxloader.c b/tools/firmware/vmxassist/vmxloader.c
index c2273f3ca1..519355b8fc 100644
--- a/tools/firmware/vmxassist/vmxloader.c
+++ b/tools/firmware/vmxassist/vmxloader.c
@@ -27,6 +27,7 @@
#ifdef _ACPI_
#include "acpi.h"
#include "../acpi/acpi2_0.h" // for ACPI_PHYSICAL_ADDRESS
+int acpi_madt_update(unsigned char* acpi_start);
#endif
@@ -110,7 +111,10 @@ main()
}
#ifdef _ACPI_
puts("Loading ACPI ...\n");
- if (ACPI_PHYSICAL_ADDRESS+sizeof(acpi) <= 0xF0000 ){
+
+ acpi_madt_update(acpi);
+
+ if (ACPI_PHYSICAL_ADDRESS+sizeof(acpi) <= 0xF0000) {
/* make sure acpi table does not overlap rombios
* currently acpi less than 8K will be OK.
*/