diff options
author | kaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk> | 2005-09-20 09:02:43 +0000 |
---|---|---|
committer | kaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk> | 2005-09-20 09:02:43 +0000 |
commit | 8ad67b4949d5df99c8cdecb0619990ce73e6700d (patch) | |
tree | 917f6a8675e41ac4c2dfb06c675e1c8fd9838267 /tools/firmware | |
parent | e02527cc82e38280b04f7c6a2c42effd8cdb4e62 (diff) | |
download | xen-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.c | 53 | ||||
-rw-r--r-- | tools/firmware/acpi/acpi_madt.h | 6 | ||||
-rw-r--r-- | tools/firmware/vmxassist/Makefile | 6 | ||||
-rw-r--r-- | tools/firmware/vmxassist/acpi_madt.c | 145 | ||||
-rw-r--r-- | tools/firmware/vmxassist/vmxloader.c | 6 |
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. */ |