mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
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>
This commit is contained in:
1 parent
e02527cc82
commit
8ad67b4949
6 files changed
+200
-46
No files matched your search
@@ -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,
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
@@ -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 ()
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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:
|
||||
*/
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -107,6 +107,33 @@ static void build_e820map(struct mem_map *mem_mapp, unsigned long mem_size)
|
||||
mem_mapp->nr_map = nr_map;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use E820 reserved memory 0x9F800 to pass number of vcpus to vmxloader
|
||||
* vmxloader will use it to config ACPI MADT table
|
||||
*/
|
||||
#define VCPU_MAGIC 0x76637075 /* "vcpu" */
|
||||
static int
|
||||
set_nr_vcpus(int xc_handle, u32 dom, unsigned long *pfn_list,
|
||||
struct domain_setup_info *dsi, unsigned long vcpus)
|
||||
{
|
||||
char *va_map;
|
||||
unsigned long *va_vcpus;
|
||||
|
||||
va_map = xc_map_foreign_range(
|
||||
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
|
||||
pfn_list[(0x9F000 - dsi->v_start) >> PAGE_SHIFT]);
|
||||
if ( va_map == NULL )
|
||||
return -1;
|
||||
|
||||
va_vcpus = (unsigned long *)(va_map + 0x800);
|
||||
*va_vcpus++ = VCPU_MAGIC;
|
||||
*va_vcpus++ = vcpus;
|
||||
|
||||
munmap(va_map, PAGE_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __i386__
|
||||
static int zap_mmio_range(int xc_handle, u32 dom,
|
||||
l2_pgentry_32_t *vl2tab,
|
||||
@@ -496,7 +523,8 @@ static int setup_guest(int xc_handle,
|
||||
MMU_MACHPHYS_UPDATE, count) )
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
|
||||
set_nr_vcpus(xc_handle, dom, page_array, &dsi, vcpus);
|
||||
|
||||
if ((boot_paramsp = xc_map_foreign_range(
|
||||
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
|
||||
|
||||