mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
it to interrogate Xen version information. Also add support for HVM hypercall execution on 64-bit host. Signed-off-by: Steven Smith <ssmith@xensource.com> Signed-off-by: Keir Fraser <keir@xensource.com>
189 lines
4.1 KiB
C
189 lines
4.1 KiB
C
/*
|
|
* 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"
|
|
#include "util.h"
|
|
#include <xen/hvm/hvm_info_table.h>
|
|
|
|
#define NULL ((void*)0)
|
|
|
|
static struct hvm_info_table *table = NULL;
|
|
|
|
static int validate_hvm_info(struct hvm_info_table *t)
|
|
{
|
|
char signature[] = "HVM INFO";
|
|
uint8_t *ptr = (uint8_t *)t;
|
|
uint8_t sum = 0;
|
|
int i;
|
|
|
|
/* strncmp(t->signature, "HVM INFO", 8) */
|
|
for (i = 0; i < 8; i++) {
|
|
if (signature[i] != t->signature[i]) {
|
|
puts("Bad hvm info signature\n");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < t->length; i++)
|
|
sum += ptr[i];
|
|
|
|
return (sum == 0);
|
|
}
|
|
|
|
/* xc_vmx_builder wrote hvm info at 0x9F800. Return it. */
|
|
struct hvm_info_table *
|
|
get_hvm_info_table(void)
|
|
{
|
|
struct hvm_info_table *t;
|
|
|
|
if (table != NULL)
|
|
return table;
|
|
|
|
t = (struct hvm_info_table *)HVM_INFO_PADDR;
|
|
|
|
if (!validate_hvm_info(t)) {
|
|
puts("Bad hvm info table\n");
|
|
return NULL;
|
|
}
|
|
|
|
table = t;
|
|
|
|
return table;
|
|
}
|
|
|
|
int
|
|
get_vcpu_nr(void)
|
|
{
|
|
struct hvm_info_table *t = get_hvm_info_table();
|
|
return (t ? t->nr_vcpus : 1); /* default 1 vcpu */
|
|
}
|
|
|
|
int
|
|
get_acpi_enabled(void)
|
|
{
|
|
struct hvm_info_table *t = get_hvm_info_table();
|
|
return (t ? t->acpi_enabled : 0); /* default no acpi */
|
|
}
|
|
|
|
|
|
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_vcpu_nr(), 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:
|
|
*/
|