[HVM] Move PCI and PCI-ISA bridge setup to hvmloader.

Signed-off-by: Keir Fraser <keir@xensource.com>
This commit is contained in:
kfraser@localhost.localdomain committed 2006-11-22 17:50:20 +00:00
1 parent 9fd9cc0666
commit bbfa22f8c9
11 files changed
+1065 -838

No files matched your search

+22 -20
View File
@@ -35,32 +35,34 @@ static int validate_hvm_info(struct hvm_info_table *t)
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");
for ( i = 0; i < 8; i++ )
{
if ( signature[i] != t->signature[i] )
{
printf("Bad hvm info signature\n");
return 0;
}
}
for (i = 0; i < t->length; i++)
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 *get_hvm_info_table(void)
{
struct hvm_info_table *t;
if (table != NULL)
if ( table != NULL )
return table;
t = (struct hvm_info_table *)HVM_INFO_PADDR;
if (!validate_hvm_info(t)) {
puts("Bad hvm info table\n");
if ( !validate_hvm_info(t) )
{
printf("Bad hvm info table\n");
return NULL;
}
@@ -69,15 +71,13 @@ get_hvm_info_table(void)
return table;
}
int
get_vcpu_nr(void)
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)
int get_acpi_enabled(void)
{
struct hvm_info_table *t = get_hvm_info_table();
return (t ? t->acpi_enabled : 0); /* default no acpi */
@@ -91,13 +91,14 @@ acpi_madt_get_madt(unsigned char *acpi_start)
struct acpi_20_madt *madt;
rsdt = acpi_rsdt_get(acpi_start);
if (rsdt == NULL)
if ( rsdt == NULL )
return NULL;
madt = (struct acpi_20_madt *)(acpi_start + rsdt->entry[1] -
ACPI_PHYSICAL_ADDRESS);
if (madt->header.header.signature != ACPI_2_0_MADT_SIGNATURE) {
puts("Bad MADT signature \n");
if ( madt->header.header.signature != ACPI_2_0_MADT_SIGNATURE )
{
printf("Bad MADT signature \n");
return NULL;
}
@@ -111,10 +112,11 @@ acpi_madt_set_local_apics(
{
int i;
if ((nr_vcpu > MAX_VIRT_CPUS) || (nr_vcpu < 0) || !madt)
if ( (nr_vcpu > MAX_VIRT_CPUS) || (nr_vcpu < 0) || !madt )
return -1;
for (i = 0; i < nr_vcpu; i++) {
for ( i = 0; i < nr_vcpu; i++ )
{
madt->lapic[i].type = ACPI_PROCESSOR_LOCAL_APIC;
madt->lapic[i].length = sizeof(struct acpi_20_madt_lapic);
madt->lapic[i].acpi_processor_id = i;
@@ -137,11 +139,11 @@ int acpi_madt_update(unsigned char *acpi_start)
struct acpi_20_madt *madt;
madt = acpi_madt_get_madt(acpi_start);
if (!madt)
if ( !madt )
return -1;
rc = acpi_madt_set_local_apics(get_vcpu_nr(), madt);
if (rc != 0)
if ( rc != 0 )
return rc;
set_checksum(
+8 -7
View File
@@ -78,7 +78,7 @@ static void acpi_tpm_tis_probe(unsigned char *acpi_start,
sizeof(tis_did_vid_rid)) != 0 )
return;
puts("TIS is available\n");
printf("TIS is available\n");
addr = acpi_xsdt_add_entry(acpi_start, freemem, limit,
AmlCode_TPM, sizeof(AmlCode_TPM));
if ( addr == NULL )
@@ -133,7 +133,7 @@ struct acpi_20_rsdt *acpi_rsdt_get(unsigned char *acpi_start)
rsdp = (struct acpi_20_rsdp *)(acpi_start + sizeof(struct acpi_20_facs));
if ( rsdp->signature != ACPI_2_0_RSDP_SIGNATURE )
{
puts("Bad RSDP signature\n");
printf("Bad RSDP signature\n");
return NULL;
}
@@ -141,7 +141,7 @@ struct acpi_20_rsdt *acpi_rsdt_get(unsigned char *acpi_start)
(acpi_start + rsdp->rsdt_address - ACPI_PHYSICAL_ADDRESS);
if ( rsdt->header.signature != ACPI_2_0_RSDT_SIGNATURE )
{
puts("Bad RSDT signature\n");
printf("Bad RSDT signature\n");
return NULL;
}
@@ -192,7 +192,7 @@ struct acpi_20_xsdt *acpi_xsdt_get(unsigned char *acpi_start)
rsdp = (struct acpi_20_rsdp *)(acpi_start + sizeof(struct acpi_20_facs));
if ( rsdp->signature != ACPI_2_0_RSDP_SIGNATURE )
{
puts("Bad RSDP signature\n");
printf("Bad RSDP signature\n");
return NULL;
}
@@ -200,7 +200,7 @@ struct acpi_20_xsdt *acpi_xsdt_get(unsigned char *acpi_start)
(acpi_start + rsdp->xsdt_address - ACPI_PHYSICAL_ADDRESS);
if ( xsdt->header.signature != ACPI_2_0_XSDT_SIGNATURE )
{
puts("Bad XSDT signature\n");
printf("Bad XSDT signature\n");
return NULL;
}
return xsdt;
@@ -270,8 +270,9 @@ static unsigned char *acpi_xsdt_add_entry(unsigned char *acpi_start,
if ( found )
{
/* memory below hard limit ? */
if (*freemem + table_size <= limit) {
puts("Copying SSDT entry!\n");
if ( (*freemem + table_size) <= limit )
{
printf("Copying SSDT entry\n");
addr = *freemem;
memcpy(addr, table, table_size);
*freemem += table_size;
+3
View File
@@ -7,4 +7,7 @@
#define LAPIC_BASE_ADDRESS 0xfee00000
#define PCI_ISA_DEVFN 0x08 /* dev 1, fn 0 */
#define PCI_ISA_IRQ_MASK 0x0c60U /* ISA IRQs 5,6,10,11 are PCI connected */
#endif /* __HVMLOADER_CONFIG_H__ */
+140 -27
View File
@@ -1,13 +1,11 @@
/*
* hvmloader.c: HVM ROMBIOS/VGABIOS/ACPI/VMXAssist image loader.
*
* A quicky so that we can boot rom images as if they were a Linux kernel.
* This code will copy the rom images (ROMBIOS/VGABIOS/VM86) into their
* respective spaces and transfer control to VM86 to execute the BIOSes.
*
* Leendert van Doorn, leendert@watson.ibm.com
* Copyright (c) 2005, International Business Machines Corporation.
*
* Copyright (c) 2006, Keir Fraser, XenSource Inc.
*
* 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.
@@ -28,8 +26,10 @@
#include "acpi_utils.h"
#include "smbios.h"
#include "config.h"
#include "pci_regs.h"
#include <xen/version.h>
#include <xen/hvm/params.h>
#include <xen/hvm/e820.h>
/* memory map */
#define HYPERCALL_PHYSICAL_ADDRESS 0x00080000
@@ -125,7 +125,7 @@ init_hypercalls(void)
{
uint32_t eax, ebx, ecx, edx;
unsigned long i;
char signature[13], number[13];
char signature[13];
xen_extraversion_t extraversion;
cpuid(0x40000000, &eax, &ebx, &ecx, &edx);
@@ -137,25 +137,19 @@ init_hypercalls(void)
if ( strcmp("XenVMMXenVMM", signature) || (eax < 0x40000002) )
{
puts("FATAL: Xen hypervisor not detected\n");
printf("FATAL: Xen hypervisor not detected\n");
__asm__ __volatile__( "ud2" );
}
cpuid(0x40000001, &eax, &ebx, &ecx, &edx);
puts("Detected Xen v");
puts(itoa(number, eax >> 16));
puts(".");
puts(itoa(number, eax & 0xffff));
/* Fill in hypercall transfer pages. */
cpuid(0x40000002, &eax, &ebx, &ecx, &edx);
for ( i = 0; i < eax; i++ )
wrmsr(ebx, HYPERCALL_PHYSICAL_ADDRESS + (i << 12) + i);
/* Print version information. */
cpuid(0x40000001, &eax, &ebx, &ecx, &edx);
hypercall_xen_version(XENVER_extraversion, extraversion);
puts(extraversion);
puts("\n");
printf("Detected Xen v%u.%u%s\n", eax >> 16, eax & 0xffff, extraversion);
}
static void apic_setup(void)
@@ -172,38 +166,157 @@ static void apic_setup(void)
*iowin = IOAPIC_ID;
}
static void pci_setup(void)
{
uint32_t devfn, bar_reg, bar_data, bar_sz, cmd;
uint32_t *base, io_base = 0xc000, mem_base = HVM_BELOW_4G_MMIO_START;
uint16_t class, vendor_id, device_id;
unsigned int bar, pin, link, isa_irq;
/* Program PCI-ISA bridge with appropriate link routes. */
link = 0;
for ( isa_irq = 0; isa_irq < 15; isa_irq++ )
{
if ( !(PCI_ISA_IRQ_MASK & (1U << isa_irq)) )
continue;
pci_writeb(PCI_ISA_DEVFN, 0x60 + link, isa_irq);
printf("PCI-ISA link %u routed to IRQ%u\n", link, isa_irq);
if ( link++ == 4 )
break;
}
/* Program ELCR to match PCI-wired IRQs. */
outb(0x4d0, (uint8_t)(PCI_ISA_IRQ_MASK >> 0));
outb(0x4d1, (uint8_t)(PCI_ISA_IRQ_MASK >> 8));
/* Scan the PCI bus and map resources. */
for ( devfn = 0; devfn < 128; devfn++ )
{
class = pci_readw(devfn, PCI_CLASS_DEVICE);
vendor_id = pci_readw(devfn, PCI_VENDOR_ID);
device_id = pci_readw(devfn, PCI_DEVICE_ID);
if ( (vendor_id == 0xffff) && (device_id == 0xffff) )
continue;
ASSERT((devfn != PCI_ISA_DEVFN) ||
((vendor_id == 0x8086) && (device_id == 0x7000)));
switch ( class )
{
case 0x0680:
ASSERT((vendor_id == 0x8086) && (device_id == 0x7113));
/*
* PIIX4 ACPI PM. Special device with special PCI config space.
* No ordinary BARs.
*/
pci_writew(devfn, 0x20, 0x0000); /* No smb bus IO enable */
pci_writew(devfn, 0x22, 0x0000);
pci_writew(devfn, 0x3c, 0x0009); /* Hardcoded IRQ9 */
pci_writew(devfn, 0x3d, 0x0001);
break;
case 0x0101:
/* PIIX3 IDE */
ASSERT((vendor_id == 0x8086) && (device_id == 0x7010));
pci_writew(devfn, 0x40, 0x8000); /* enable IDE0 */
pci_writew(devfn, 0x42, 0x8000); /* enable IDE1 */
/* fall through */
default:
/* Default memory mappings. */
for ( bar = 0; bar < 7; bar++ )
{
bar_reg = PCI_BASE_ADDRESS_0 + 4*bar;
if ( bar == 6 )
bar_reg = PCI_ROM_ADDRESS;
bar_data = pci_readl(devfn, bar_reg);
pci_writel(devfn, bar_reg, ~0);
bar_sz = pci_readl(devfn, bar_reg);
if ( bar_sz == 0 )
continue;
if ( (bar_data & PCI_BASE_ADDRESS_SPACE) ==
PCI_BASE_ADDRESS_SPACE_MEMORY )
{
base = &mem_base;
bar_sz &= PCI_BASE_ADDRESS_MEM_MASK;
bar_data &= ~PCI_BASE_ADDRESS_MEM_MASK;
}
else
{
base = &io_base;
bar_sz &= PCI_BASE_ADDRESS_IO_MASK & 0xffff;
bar_data &= ~PCI_BASE_ADDRESS_IO_MASK;
}
bar_sz &= ~(bar_sz - 1);
*base = (*base + bar_sz - 1) & ~(bar_sz - 1);
bar_data |= *base;
*base += bar_sz;
pci_writel(devfn, bar_reg, bar_data);
printf("pci dev %02x:%x bar %02x size %08x: %08x\n",
devfn>>3, devfn&7, bar_reg, bar_sz, bar_data);
/* Now enable the memory or I/O mapping. */
cmd = pci_readw(devfn, PCI_COMMAND);
if ( (bar_reg == PCI_ROM_ADDRESS) ||
((bar_data & PCI_BASE_ADDRESS_SPACE) ==
PCI_BASE_ADDRESS_SPACE_MEMORY) )
cmd |= PCI_COMMAND_MEMORY;
else
cmd |= PCI_COMMAND_IO;
pci_writew(devfn, PCI_COMMAND, cmd);
}
break;
}
/* Map the interrupt. */
pin = pci_readb(devfn, PCI_INTERRUPT_PIN);
if ( pin != 0 )
{
/* This is the barber's pole mapping used by Xen. */
link = ((pin - 1) + (devfn >> 3)) & 3;
isa_irq = pci_readb(PCI_ISA_DEVFN, 0x60 + link);
pci_writeb(devfn, PCI_INTERRUPT_LINE, isa_irq);
printf("pci dev %02x:%x INT%c->IRQ%u\n",
devfn>>3, devfn&7, 'A'+pin-1, isa_irq);
}
}
}
int main(void)
{
puts("HVM Loader\n");
printf("HVM Loader\n");
init_hypercalls();
puts("Writing SMBIOS tables ...\n");
printf("Writing SMBIOS tables ...\n");
hvm_write_smbios_tables();
puts("Loading ROMBIOS ...\n");
printf("Loading ROMBIOS ...\n");
memcpy((void *)ROMBIOS_PHYSICAL_ADDRESS, rombios, sizeof(rombios));
apic_setup();
pci_setup();
create_mp_tables();
if ( cirrus_check() )
{
puts("Loading Cirrus VGABIOS ...\n");
printf("Loading Cirrus VGABIOS ...\n");
memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
vgabios_cirrusvga, sizeof(vgabios_cirrusvga));
}
else
{
puts("Loading Standard VGABIOS ...\n");
printf("Loading Standard VGABIOS ...\n");
memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
vgabios_stdvga, sizeof(vgabios_stdvga));
}
if ( get_acpi_enabled() != 0 )
{
puts("Loading ACPI ...\n");
printf("Loading ACPI ...\n");
acpi_madt_update((unsigned char *) acpi);
if ( (ACPI_PHYSICAL_ADDRESS + sizeof(acpi)) <= 0xF0000 )
{
@@ -225,23 +338,23 @@ int main(void)
if ( check_amd() )
{
/* AMD implies this is SVM */
puts("SVM go ...\n");
printf("SVM go ...\n");
vmmcall(SVM_VMMCALL_RESET_TO_REALMODE, 0, 0, 0, 0, 0);
}
else
{
puts("Loading VMXAssist ...\n");
printf("Loading VMXAssist ...\n");
memcpy((void *)VMXASSIST_PHYSICAL_ADDRESS,
vmxassist, sizeof(vmxassist));
puts("VMX go ...\n");
printf("VMX go ...\n");
__asm__ __volatile__(
"jmp *%%eax"
: : "a" (VMXASSIST_PHYSICAL_ADDRESS), "d" (0)
);
}
puts("Failed to invoke ROMBIOS\n");
printf("Failed to invoke ROMBIOS\n");
return 0;
}
+3 -6
View File
@@ -263,10 +263,7 @@ void fill_mp_io_intr_entry(
{
mpiie->type = ENTRY_TYPE_IO_INTR;
mpiie->intr_type = INTR_TYPE_INT;
mpiie->io_intr_flags = 0;
/* IRQs 10 and 11 are PCI, so level triggered and active low. */
if ( (src_bus_irq == 10) || (src_bus_irq == 11) )
mpiie->io_intr_flags = 0xf;
mpiie->io_intr_flags = (PCI_ISA_IRQ_MASK & (1U<<src_bus_irq)) ? 0xf : 0x0;
mpiie->src_bus_id = src_bus_id;
mpiie->src_bus_irq = src_bus_irq;
mpiie->dst_ioapic_id = ioapic_id;
@@ -349,13 +346,13 @@ void create_mp_tables(void)
vcpu_nr = get_vcpu_nr();
puts("Creating MP tables ...\n");
printf("Creating MP tables ...\n");
/* Find the 'safe' place in ROMBIOS for the MP tables. */
mp_table_base = get_mp_table_start();
if ( mp_table_base == NULL )
{
puts("Couldn't find start point for MP tables\n");
printf("Couldn't find start point for MP tables\n");
return;
}
+108
View File
@@ -0,0 +1,108 @@
/*
* pci_regs.h
*
* PCI standard defines
* Copyright 1994, Drew Eckhardt
* Copyright 1997--1999 Martin Mares <mj@ucw.cz>
*
* For more information, please consult the following manuals (look at
* http://www.pcisig.com/ for how to get them):
*
* PCI BIOS Specification
* PCI Local Bus Specification
* PCI to PCI Bridge Specification
* PCI System Design Guide
*/
#ifndef __HVMLOADER_PCI_REGS_H__
#define __HVMLOADER_PCI_REGS_H__
#define PCI_VENDOR_ID 0x00 /* 16 bits */
#define PCI_DEVICE_ID 0x02 /* 16 bits */
#define PCI_COMMAND 0x04 /* 16 bits */
#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */
#define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */
#define PCI_COMMAND_MASTER 0x4 /* Enable bus mastering */
#define PCI_COMMAND_SPECIAL 0x8 /* Enable response to special cycles */
#define PCI_COMMAND_INVALIDATE 0x10 /* Use memory write and invalidate */
#define PCI_COMMAND_VGA_PALETTE 0x20 /* Enable palette snooping */
#define PCI_COMMAND_PARITY 0x40 /* Enable parity checking */
#define PCI_COMMAND_WAIT 0x80 /* Enable address/data stepping */
#define PCI_COMMAND_SERR 0x100 /* Enable SERR */
#define PCI_COMMAND_FAST_BACK 0x200 /* Enable back-to-back writes */
#define PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */
#define PCI_STATUS 0x06 /* 16 bits */
#define PCI_STATUS_CAP_LIST 0x10 /* Support Capability List */
#define PCI_STATUS_66MHZ 0x20 /* Support 66 Mhz PCI 2.1 bus */
#define PCI_STATUS_UDF 0x40 /* Support User Definable Features [obsolete] */
#define PCI_STATUS_FAST_BACK 0x80 /* Accept fast-back to back */
#define PCI_STATUS_PARITY 0x100 /* Detected parity error */
#define PCI_STATUS_DEVSEL_MASK 0x600 /* DEVSEL timing */
#define PCI_STATUS_DEVSEL_FAST 0x000
#define PCI_STATUS_DEVSEL_MEDIUM 0x200
#define PCI_STATUS_DEVSEL_SLOW 0x400
#define PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */
#define PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */
#define PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */
#define PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */
#define PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */
#define PCI_CLASS_REVISION 0x08 /* High 24 bits are class, low 8 revision */
#define PCI_REVISION_ID 0x08 /* Revision ID */
#define PCI_CLASS_PROG 0x09 /* Reg. Level Programming Interface */
#define PCI_CLASS_DEVICE 0x0a /* Device class */
#define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */
#define PCI_LATENCY_TIMER 0x0d /* 8 bits */
#define PCI_HEADER_TYPE 0x0e /* 8 bits */
#define PCI_HEADER_TYPE_NORMAL 0
#define PCI_HEADER_TYPE_BRIDGE 1
#define PCI_HEADER_TYPE_CARDBUS 2
#define PCI_BIST 0x0f /* 8 bits */
#define PCI_BIST_CODE_MASK 0x0f /* Return result */
#define PCI_BIST_START 0x40 /* 1 to start BIST, 2 secs or less */
#define PCI_BIST_CAPABLE 0x80 /* 1 if BIST capable */
/*
* Base addresses specify locations in memory or I/O space.
* Decoded size can be determined by writing a value of
* 0xffffffff to the register, and reading it back. Only
* 1 bits are decoded.
*/
#define PCI_BASE_ADDRESS_0 0x10 /* 32 bits */
#define PCI_BASE_ADDRESS_1 0x14 /* 32 bits [htype 0,1 only] */
#define PCI_BASE_ADDRESS_2 0x18 /* 32 bits [htype 0 only] */
#define PCI_BASE_ADDRESS_3 0x1c /* 32 bits */
#define PCI_BASE_ADDRESS_4 0x20 /* 32 bits */
#define PCI_BASE_ADDRESS_5 0x24 /* 32 bits */
#define PCI_BASE_ADDRESS_SPACE 0x01 /* 0 = memory, 1 = I/O */
#define PCI_BASE_ADDRESS_SPACE_IO 0x01
#define PCI_BASE_ADDRESS_SPACE_MEMORY 0x00
#define PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06
#define PCI_BASE_ADDRESS_MEM_TYPE_32 0x00 /* 32 bit address */
#define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M [obsolete] */
#define PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 /* 64 bit address */
#define PCI_BASE_ADDRESS_MEM_PREFETCH 0x08 /* prefetchable? */
#define PCI_BASE_ADDRESS_MEM_MASK (~0x0fUL)
#define PCI_BASE_ADDRESS_IO_MASK (~0x03UL)
/* bit 1 is reserved if address_space = 1 */
/* Header type 0 (normal devices) */
#define PCI_CARDBUS_CIS 0x28
#define PCI_SUBSYSTEM_VENDOR_ID 0x2c
#define PCI_SUBSYSTEM_ID 0x2e
#define PCI_ROM_ADDRESS 0x30 /* Bits 31..11 are address, 10..1 reserved */
#define PCI_ROM_ADDRESS_ENABLE 0x01
#define PCI_ROM_ADDRESS_MASK (~0x7ffUL)
#define PCI_CAPABILITY_LIST 0x34 /* Offset of first capability list entry */
/* 0x35-0x3b are reserved */
#define PCI_INTERRUPT_LINE 0x3c /* 8 bits */
#define PCI_INTERRUPT_PIN 0x3d /* 8 bits */
#define PCI_MIN_GNT 0x3e /* 8 bits */
#define PCI_MAX_LAT 0x3f /* 8 bits */
#endif /* __HVMLOADER_PCI_REGS_H__ */
+347 -336
View File
@@ -30,29 +30,29 @@
static size_t
write_smbios_tables(void *start,
uint32_t vcpus, uint64_t memsize,
uint8_t uuid[16], char *xen_version,
uint32_t xen_major_version, uint32_t xen_minor_version);
uint32_t vcpus, uint64_t memsize,
uint8_t uuid[16], char *xen_version,
uint32_t xen_major_version, uint32_t xen_minor_version);
static void
get_cpu_manufacturer(char *buf, int len);
static void
smbios_entry_point_init(void *start,
uint16_t max_structure_size,
uint16_t structure_table_length,
uint32_t structure_table_address,
uint16_t number_of_structures);
uint16_t max_structure_size,
uint16_t structure_table_length,
uint32_t structure_table_address,
uint16_t number_of_structures);
static void *
smbios_type_0_init(void *start, const char *xen_version,
uint32_t xen_major_version, uint32_t xen_minor_version);
uint32_t xen_major_version, uint32_t xen_minor_version);
static void *
smbios_type_1_init(void *start, const char *xen_version,
uint8_t uuid[16]);
uint8_t uuid[16]);
static void *
smbios_type_3_init(void *start);
static void *
smbios_type_4_init(void *start, unsigned int cpu_number,
char *cpu_manufacturer);
char *cpu_manufacturer);
static void *
smbios_type_16_init(void *start, uint32_t memory_size_mb);
static void *
@@ -69,64 +69,64 @@ smbios_type_127_init(void *start);
static void
get_cpu_manufacturer(char *buf, int len)
{
char id[12];
uint32_t eax = 0;
char id[12];
uint32_t eax = 0;
cpuid(0, &eax, (uint32_t *)&id[0], (uint32_t *)&id[8],
(uint32_t *)&id[4]);
cpuid(0, &eax, (uint32_t *)&id[0], (uint32_t *)&id[8],
(uint32_t *)&id[4]);
if (memcmp(id, "GenuineIntel", 12) == 0)
strncpy(buf, "Intel", len);
else if (memcmp(id, "AuthenticAMD", 12) == 0)
strncpy(buf, "AMD", len);
else
strncpy(buf, "unknown", len);
if (memcmp(id, "GenuineIntel", 12) == 0)
strncpy(buf, "Intel", len);
else if (memcmp(id, "AuthenticAMD", 12) == 0)
strncpy(buf, "AMD", len);
else
strncpy(buf, "unknown", len);
}
static size_t
write_smbios_tables(void *start,
uint32_t vcpus, uint64_t memsize,
uint8_t uuid[16], char *xen_version,
uint32_t xen_major_version, uint32_t xen_minor_version)
uint32_t vcpus, uint64_t memsize,
uint8_t uuid[16], char *xen_version,
uint32_t xen_major_version, uint32_t xen_minor_version)
{
unsigned cpu_num, nr_structs = 0, max_struct_size = 0;
char *p, *q;
char cpu_manufacturer[15];
unsigned cpu_num, nr_structs = 0, max_struct_size = 0;
char *p, *q;
char cpu_manufacturer[15];
get_cpu_manufacturer(cpu_manufacturer, 15);
get_cpu_manufacturer(cpu_manufacturer, 15);
p = (char *)start + sizeof(struct smbios_entry_point);
p = (char *)start + sizeof(struct smbios_entry_point);
#define do_struct(fn) do { \
q = (fn); \
nr_structs++; \
if ((q - p) > max_struct_size) \
max_struct_size = q - p; \
p = q; \
#define do_struct(fn) do { \
q = (fn); \
nr_structs++; \
if ( (q - p) > max_struct_size ) \
max_struct_size = q - p; \
p = q; \
} while (0)
do_struct(smbios_type_0_init(p, xen_version, xen_major_version,
xen_minor_version));
do_struct(smbios_type_1_init(p, xen_version, uuid));
do_struct(smbios_type_3_init(p));
for (cpu_num = 1; cpu_num <= vcpus; cpu_num++)
do_struct(smbios_type_4_init(p, cpu_num, cpu_manufacturer));
do_struct(smbios_type_16_init(p, memsize));
do_struct(smbios_type_17_init(p, memsize));
do_struct(smbios_type_19_init(p, memsize));
do_struct(smbios_type_20_init(p, memsize));
do_struct(smbios_type_32_init(p));
do_struct(smbios_type_127_init(p));
do_struct(smbios_type_0_init(p, xen_version, xen_major_version,
xen_minor_version));
do_struct(smbios_type_1_init(p, xen_version, uuid));
do_struct(smbios_type_3_init(p));
for ( cpu_num = 1; cpu_num <= vcpus; cpu_num++ )
do_struct(smbios_type_4_init(p, cpu_num, cpu_manufacturer));
do_struct(smbios_type_16_init(p, memsize));
do_struct(smbios_type_17_init(p, memsize));
do_struct(smbios_type_19_init(p, memsize));
do_struct(smbios_type_20_init(p, memsize));
do_struct(smbios_type_32_init(p));
do_struct(smbios_type_127_init(p));
#undef do_struct
smbios_entry_point_init(
start, max_struct_size,
(p - (char *)start) - sizeof(struct smbios_entry_point),
SMBIOS_PHYSICAL_ADDRESS + sizeof(struct smbios_entry_point),
nr_structs);
smbios_entry_point_init(
start, max_struct_size,
(p - (char *)start) - sizeof(struct smbios_entry_point),
SMBIOS_PHYSICAL_ADDRESS + sizeof(struct smbios_entry_point),
nr_structs);
return (size_t)((char *)p - (char *)start);
return (size_t)((char *)p - (char *)start);
}
/* This tries to figure out how much pseudo-physical memory (in MB)
@@ -142,428 +142,439 @@ write_smbios_tables(void *start,
static uint64_t
get_memsize(void)
{
struct e820entry *map = NULL;
uint8_t num_entries = 0;
uint64_t memsize = 0;
uint8_t i;
struct e820entry *map = NULL;
uint8_t num_entries = 0;
uint64_t memsize = 0;
uint8_t i;
map = (struct e820entry *) (E820_MAP_PAGE + E820_MAP_OFFSET);
num_entries = *((uint8_t *) (E820_MAP_PAGE + E820_MAP_NR_OFFSET));
map = (struct e820entry *) (E820_MAP_PAGE + E820_MAP_OFFSET);
num_entries = *((uint8_t *) (E820_MAP_PAGE + E820_MAP_NR_OFFSET));
/* walk through e820map, ignoring any entries that aren't marked
as usable or reserved. */
/* walk through e820map, ignoring any entries that aren't marked
as usable or reserved. */
for (i = 0; i < num_entries; i++) {
if (map->type == E820_RAM || map->type == E820_RESERVED)
memsize += map->size;
map++;
}
for ( i = 0; i < num_entries; i++ )
{
if (map->type == E820_RAM || map->type == E820_RESERVED)
memsize += map->size;
map++;
}
/* Round up to the nearest MB. The user specifies domU
pseudo-physical memory in megabytes, so not doing this
could easily lead to reporting one less MB than the user
specified. */
if (memsize & ((1<<20)-1))
memsize = (memsize >> 20) + 1;
else
memsize = (memsize >> 20);
/* Round up to the nearest MB. The user specifies domU
pseudo-physical memory in megabytes, so not doing this
could easily lead to reporting one less MB than the user
specified. */
if ( memsize & ((1<<20)-1) )
memsize = (memsize >> 20) + 1;
else
memsize = (memsize >> 20);
return memsize;
return memsize;
}
void
hvm_write_smbios_tables(void)
{
uint8_t uuid[16]; /* ** This will break if xen_domain_handle_t is
not uint8_t[16]. ** */
uint16_t xen_major_version, xen_minor_version;
uint32_t xen_version;
char xen_extra_version[XEN_EXTRAVERSION_LEN];
/* guess conservatively on buffer length for Xen version string */
char xen_version_str[80];
/* temporary variables used to build up Xen version string */
char *p = NULL; /* points to next point of insertion */
unsigned len = 0; /* length of string already composed */
char *tmp = NULL; /* holds result of itoa() */
unsigned tmp_len; /* length of next string to add */
uint8_t uuid[16]; /* ** This will break if xen_domain_handle_t is
not uint8_t[16]. ** */
uint16_t xen_major_version, xen_minor_version;
uint32_t xen_version;
char xen_extra_version[XEN_EXTRAVERSION_LEN];
/* guess conservatively on buffer length for Xen version string */
char xen_version_str[80];
/* temporary variables used to build up Xen version string */
char *p = NULL; /* points to next point of insertion */
unsigned len = 0; /* length of string already composed */
char *tmp = NULL; /* holds result of itoa() */
unsigned tmp_len; /* length of next string to add */
hypercall_xen_version(XENVER_guest_handle, uuid);
hypercall_xen_version(XENVER_guest_handle, uuid);
/* xen_version major and minor */
xen_version = hypercall_xen_version(XENVER_version, NULL);
xen_major_version = (uint16_t) (xen_version >> 16);
xen_minor_version = (uint16_t) xen_version;
/* xen_version major and minor */
xen_version = hypercall_xen_version(XENVER_version, NULL);
xen_major_version = (uint16_t) (xen_version >> 16);
xen_minor_version = (uint16_t) xen_version;
hypercall_xen_version(XENVER_extraversion, xen_extra_version);
hypercall_xen_version(XENVER_extraversion, xen_extra_version);
/* build up human-readable Xen version string */
p = xen_version_str;
len = 0;
/* build up human-readable Xen version string */
p = xen_version_str;
len = 0;
itoa(tmp, xen_major_version);
tmp_len = strlen(tmp);
len += tmp_len;
if (len >= sizeof(xen_version_str))
goto error_out;
strcpy(p, tmp);
p += tmp_len;
itoa(tmp, xen_major_version);
tmp_len = strlen(tmp);
len += tmp_len;
if ( len >= sizeof(xen_version_str) )
goto error_out;
strcpy(p, tmp);
p += tmp_len;
len++;
if (len >= sizeof(xen_version_str))
goto error_out;
*p = '.';
p++;
len++;
if ( len >= sizeof(xen_version_str) )
goto error_out;
*p = '.';
p++;
itoa(tmp, xen_minor_version);
tmp_len = strlen(tmp);
len += tmp_len;
if (len >= sizeof(xen_version_str))
goto error_out;
strcpy(p, tmp);
p += tmp_len;
itoa(tmp, xen_minor_version);
tmp_len = strlen(tmp);
len += tmp_len;
if ( len >= sizeof(xen_version_str) )
goto error_out;
strcpy(p, tmp);
p += tmp_len;
tmp_len = strlen(xen_extra_version);
len += tmp_len;
if (len >= sizeof(xen_version_str))
goto error_out;
strcpy(p, xen_extra_version);
p += tmp_len;
tmp_len = strlen(xen_extra_version);
len += tmp_len;
if ( len >= sizeof(xen_version_str) )
goto error_out;
strcpy(p, xen_extra_version);
p += tmp_len;
xen_version_str[sizeof(xen_version_str)-1] = '\0';
xen_version_str[sizeof(xen_version_str)-1] = '\0';
/* NB. 0xC0000 is a safe large memory area for scratch. */
len = write_smbios_tables((void *)0xC0000,
get_vcpu_nr(), get_memsize(),
uuid, xen_version_str,
xen_major_version, xen_minor_version);
if (len > SMBIOS_SIZE_LIMIT)
goto error_out;
/* Okay, not too large: copy out of scratch to final location. */
memcpy((void *)SMBIOS_PHYSICAL_ADDRESS, (void *)0xC0000, len);
/* NB. 0xC0000 is a safe large memory area for scratch. */
len = write_smbios_tables((void *)0xC0000,
get_vcpu_nr(), get_memsize(),
uuid, xen_version_str,
xen_major_version, xen_minor_version);
if ( len > SMBIOS_SIZE_LIMIT )
goto error_out;
/* Okay, not too large: copy out of scratch to final location. */
memcpy((void *)SMBIOS_PHYSICAL_ADDRESS, (void *)0xC0000, len);
return;
return;
error_out:
puts("Could not write SMBIOS tables, error in hvmloader.c:"
"hvm_write_smbios_tables()\n");
printf("Could not write SMBIOS tables, error in hvmloader.c:"
"hvm_write_smbios_tables()\n");
}
static void
smbios_entry_point_init(void *start,
uint16_t max_structure_size,
uint16_t structure_table_length,
uint32_t structure_table_address,
uint16_t number_of_structures)
uint16_t max_structure_size,
uint16_t structure_table_length,
uint32_t structure_table_address,
uint16_t number_of_structures)
{
uint8_t sum;
int i;
struct smbios_entry_point *ep = (struct smbios_entry_point *)start;
uint8_t sum;
int i;
struct smbios_entry_point *ep = (struct smbios_entry_point *)start;
strncpy(ep->anchor_string, "_SM_", 4);
ep->length = 0x1f;
ep->smbios_major_version = 2;
ep->smbios_minor_version = 4;
ep->max_structure_size = max_structure_size;
ep->entry_point_revision = 0;
memset(ep->formatted_area, 0, 5);
strncpy(ep->intermediate_anchor_string, "_DMI_", 5);
strncpy(ep->anchor_string, "_SM_", 4);
ep->length = 0x1f;
ep->smbios_major_version = 2;
ep->smbios_minor_version = 4;
ep->max_structure_size = max_structure_size;
ep->entry_point_revision = 0;
memset(ep->formatted_area, 0, 5);
strncpy(ep->intermediate_anchor_string, "_DMI_", 5);
ep->structure_table_length = structure_table_length;
ep->structure_table_address = structure_table_address;
ep->number_of_structures = number_of_structures;
ep->smbios_bcd_revision = 0x24;
ep->structure_table_length = structure_table_length;
ep->structure_table_address = structure_table_address;
ep->number_of_structures = number_of_structures;
ep->smbios_bcd_revision = 0x24;
ep->checksum = 0;
ep->intermediate_checksum = 0;
ep->checksum = 0;
ep->intermediate_checksum = 0;
sum = 0;
for (i = 0; i < 0x10; ++i)
sum += ((int8_t *)start)[i];
ep->checksum = -sum;
sum = 0;
for ( i = 0; i < 0x10; i++ )
sum += ((int8_t *)start)[i];
ep->checksum = -sum;
sum = 0;
for (i = 0x10; i < ep->length; ++i)
sum += ((int8_t *)start)[i];
ep->intermediate_checksum = -sum;
sum = 0;
for ( i = 0x10; i < ep->length; i++ )
sum += ((int8_t *)start)[i];
ep->intermediate_checksum = -sum;
}
/* Type 0 -- BIOS Information */
static void *
smbios_type_0_init(void *start, const char *xen_version,
uint32_t xen_major_version, uint32_t xen_minor_version)
uint32_t xen_major_version, uint32_t xen_minor_version)
{
struct smbios_type_0 *p = (struct smbios_type_0 *)start;
struct smbios_type_0 *p = (struct smbios_type_0 *)start;
p->header.type = 0;
p->header.length = sizeof(struct smbios_type_0);
p->header.handle = 0;
p->header.type = 0;
p->header.length = sizeof(struct smbios_type_0);
p->header.handle = 0;
p->vendor_str = 1;
p->version_str = 2;
p->starting_address_segment = 0xe800;
p->release_date_str = 0;
p->rom_size = 0;
p->vendor_str = 1;
p->version_str = 2;
p->starting_address_segment = 0xe800;
p->release_date_str = 0;
p->rom_size = 0;
memset(p->characteristics, 0, 8);
p->characteristics[7] = 0x08; /* BIOS characteristics not supported */
p->characteristics_extension_bytes[0] = 0;
p->characteristics_extension_bytes[1] = 0;
memset(p->characteristics, 0, 8);
p->characteristics[7] = 0x08; /* BIOS characteristics not supported */
p->characteristics_extension_bytes[0] = 0;
p->characteristics_extension_bytes[1] = 0;
p->major_release = (uint8_t) xen_major_version;
p->minor_release = (uint8_t) xen_minor_version;
p->embedded_controller_major = 0xff;
p->embedded_controller_minor = 0xff;
p->major_release = (uint8_t) xen_major_version;
p->minor_release = (uint8_t) xen_minor_version;
p->embedded_controller_major = 0xff;
p->embedded_controller_minor = 0xff;
start += sizeof(struct smbios_type_0);
strcpy((char *)start, "Xen");
start += strlen("Xen") + 1;
strcpy((char *)start, xen_version);
start += strlen(xen_version) + 1;
start += sizeof(struct smbios_type_0);
strcpy((char *)start, "Xen");
start += strlen("Xen") + 1;
strcpy((char *)start, xen_version);
start += strlen(xen_version) + 1;
*((uint8_t *)start) = 0;
return start + 1;
*((uint8_t *)start) = 0;
return start + 1;
}
/* Type 1 -- System Information */
static void *
smbios_type_1_init(void *start, const char *xen_version,
uint8_t uuid[16])
uint8_t uuid[16])
{
char uuid_str[37];
struct smbios_type_1 *p = (struct smbios_type_1 *)start;
p->header.type = 1;
p->header.length = sizeof(struct smbios_type_1);
p->header.handle = 0x100;
char uuid_str[37];
struct smbios_type_1 *p = (struct smbios_type_1 *)start;
p->header.type = 1;
p->header.length = sizeof(struct smbios_type_1);
p->header.handle = 0x100;
p->manufacturer_str = 1;
p->product_name_str = 2;
p->version_str = 3;
p->serial_number_str = 4;
p->manufacturer_str = 1;
p->product_name_str = 2;
p->version_str = 3;
p->serial_number_str = 4;
memcpy(p->uuid, uuid, 16);
memcpy(p->uuid, uuid, 16);
p->wake_up_type = 0x06; /* power switch */
p->sku_str = 0;
p->family_str = 0;
p->wake_up_type = 0x06; /* power switch */
p->sku_str = 0;
p->family_str = 0;
start += sizeof(struct smbios_type_1);
start += sizeof(struct smbios_type_1);
strcpy((char *)start, "Xen");
start += strlen("Xen") + 1;
strcpy((char *)start, "HVM domU");
start += strlen("HVM domU") + 1;
strcpy((char *)start, xen_version);
start += strlen(xen_version) + 1;
uuid_to_string(uuid_str, uuid);
strcpy((char *)start, uuid_str);
start += strlen(uuid_str) + 1;
*((uint8_t *)start) = 0;
strcpy((char *)start, "Xen");
start += strlen("Xen") + 1;
strcpy((char *)start, "HVM domU");
start += strlen("HVM domU") + 1;
strcpy((char *)start, xen_version);
start += strlen(xen_version) + 1;
uuid_to_string(uuid_str, uuid);
strcpy((char *)start, uuid_str);
start += strlen(uuid_str) + 1;
*((uint8_t *)start) = 0;
return start+1;
return start+1;
}
/* Type 3 -- System Enclosure */
static void *
smbios_type_3_init(void *start)
{
struct smbios_type_3 *p = (struct smbios_type_3 *)start;
struct smbios_type_3 *p = (struct smbios_type_3 *)start;
p->header.type = 3;
p->header.length = sizeof(struct smbios_type_3);
p->header.handle = 0x300;
p->header.type = 3;
p->header.length = sizeof(struct smbios_type_3);
p->header.handle = 0x300;
p->manufacturer_str = 1;
p->type = 0x01; /* other */
p->version_str = 0;
p->serial_number_str = 0;
p->asset_tag_str = 0;
p->boot_up_state = 0x03; /* safe */
p->power_supply_state = 0x03; /* safe */
p->thermal_state = 0x03; /* safe */
p->security_status = 0x02; /* unknown */
p->manufacturer_str = 1;
p->type = 0x01; /* other */
p->version_str = 0;
p->serial_number_str = 0;
p->asset_tag_str = 0;
p->boot_up_state = 0x03; /* safe */
p->power_supply_state = 0x03; /* safe */
p->thermal_state = 0x03; /* safe */
p->security_status = 0x02; /* unknown */
start += sizeof(struct smbios_type_3);
start += sizeof(struct smbios_type_3);
strcpy((char *)start, "Xen");
start += strlen("Xen") + 1;
*((uint8_t *)start) = 0;
return start+1;
strcpy((char *)start, "Xen");
start += strlen("Xen") + 1;
*((uint8_t *)start) = 0;
return start+1;
}
/* Type 4 -- Processor Information */
static void *
smbios_type_4_init(void *start, unsigned int cpu_number, char *cpu_manufacturer)
{
char buf[80];
struct smbios_type_4 *p = (struct smbios_type_4 *)start;
uint32_t eax, ebx, ecx, edx;
char buf[80];
struct smbios_type_4 *p = (struct smbios_type_4 *)start;
uint32_t eax, ebx, ecx, edx;
p->header.type = 4;
p->header.length = sizeof(struct smbios_type_4);
p->header.handle = 0x400 + cpu_number;
p->header.type = 4;
p->header.length = sizeof(struct smbios_type_4);
p->header.handle = 0x400 + cpu_number;
p->socket_designation_str = 1;
p->processor_type = 0x03; /* CPU */
p->processor_family = 0x01; /* other */
p->manufacturer_str = 2;
p->socket_designation_str = 1;
p->processor_type = 0x03; /* CPU */
p->processor_family = 0x01; /* other */
p->manufacturer_str = 2;
cpuid(1, &eax, &ebx, &ecx, &edx);
cpuid(1, &eax, &ebx, &ecx, &edx);
p->cpuid[0] = eax;
p->cpuid[1] = edx;
p->cpuid[0] = eax;
p->cpuid[1] = edx;
p->version_str = 0;
p->voltage = 0;
p->external_clock = 0;
p->version_str = 0;
p->voltage = 0;
p->external_clock = 0;
p->max_speed = 0; /* unknown */
p->current_speed = 0; /* unknown */
p->max_speed = 0; /* unknown */
p->current_speed = 0; /* unknown */
p->status = 0x41; /* socket populated, CPU enabled */
p->upgrade = 0x01; /* other */
p->status = 0x41; /* socket populated, CPU enabled */
p->upgrade = 0x01; /* other */
start += sizeof(struct smbios_type_4);
start += sizeof(struct smbios_type_4);
strncpy(buf, "CPU ", sizeof(buf));
if ((sizeof(buf) - strlen("CPU ")) >= 3)
itoa(buf + strlen("CPU "), cpu_number);
strncpy(buf, "CPU ", sizeof(buf));
if ( (sizeof(buf) - strlen("CPU ")) >= 3 )
itoa(buf + strlen("CPU "), cpu_number);
strcpy((char *)start, buf);
start += strlen(buf) + 1;
strcpy((char *)start, buf);
start += strlen(buf) + 1;
strcpy((char *)start, cpu_manufacturer);
start += strlen(cpu_manufacturer) + 1;
strcpy((char *)start, cpu_manufacturer);
start += strlen(cpu_manufacturer) + 1;
*((uint8_t *)start) = 0;
return start+1;
*((uint8_t *)start) = 0;
return start+1;
}
/* Type 16 -- Physical Memory Array */
static void *
smbios_type_16_init(void *start, uint32_t memsize)
{
struct smbios_type_16 *p = (struct smbios_type_16*)start;
struct smbios_type_16 *p = (struct smbios_type_16*)start;
p->header.type = 16;
p->header.handle = 0x1000;
p->header.length = sizeof(struct smbios_type_16);
p->header.type = 16;
p->header.handle = 0x1000;
p->header.length = sizeof(struct smbios_type_16);
p->location = 0x01; /* other */
p->use = 0x03; /* system memory */
p->error_correction = 0x01; /* other */
p->maximum_capacity = memsize * 1024;
p->memory_error_information_handle = 0xfffe; /* none provided */
p->number_of_memory_devices = 1;
p->location = 0x01; /* other */
p->use = 0x03; /* system memory */
p->error_correction = 0x01; /* other */
p->maximum_capacity = memsize * 1024;
p->memory_error_information_handle = 0xfffe; /* none provided */
p->number_of_memory_devices = 1;
start += sizeof(struct smbios_type_16);
*((uint16_t *)start) = 0;
return start + 2;
start += sizeof(struct smbios_type_16);
*((uint16_t *)start) = 0;
return start + 2;
}
/* Type 17 -- Memory Device */
static void *
smbios_type_17_init(void *start, uint32_t memory_size_mb)
{
struct smbios_type_17 *p = (struct smbios_type_17 *)start;
struct smbios_type_17 *p = (struct smbios_type_17 *)start;
p->header.type = 17;
p->header.length = sizeof(struct smbios_type_17);
p->header.handle = 0x1100;
p->header.type = 17;
p->header.length = sizeof(struct smbios_type_17);
p->header.handle = 0x1100;
p->physical_memory_array_handle = 0x1000;
p->total_width = 64;
p->data_width = 64;
/* truncate memory_size_mb to 16 bits and clear most significant
bit [indicates size in MB] */
p->size = (uint16_t) memory_size_mb & 0x7fff;
p->form_factor = 0x09; /* DIMM */
p->device_set = 0;
p->device_locator_str = 1;
p->bank_locator_str = 0;
p->memory_type = 0x07; /* RAM */
p->type_detail = 0;
p->physical_memory_array_handle = 0x1000;
p->total_width = 64;
p->data_width = 64;
/* truncate memory_size_mb to 16 bits and clear most significant
bit [indicates size in MB] */
p->size = (uint16_t) memory_size_mb & 0x7fff;
p->form_factor = 0x09; /* DIMM */
p->device_set = 0;
p->device_locator_str = 1;
p->bank_locator_str = 0;
p->memory_type = 0x07; /* RAM */
p->type_detail = 0;
start += sizeof(struct smbios_type_17);
strcpy((char *)start, "DIMM 1");
start += strlen("DIMM 1") + 1;
*((uint8_t *)start) = 0;
start += sizeof(struct smbios_type_17);
strcpy((char *)start, "DIMM 1");
start += strlen("DIMM 1") + 1;
*((uint8_t *)start) = 0;
return start+1;
return start+1;
}
/* Type 19 -- Memory Array Mapped Address */
static void *
smbios_type_19_init(void *start, uint32_t memory_size_mb)
{
struct smbios_type_19 *p = (struct smbios_type_19 *)start;
struct smbios_type_19 *p = (struct smbios_type_19 *)start;
p->header.type = 19;
p->header.length = sizeof(struct smbios_type_19);
p->header.handle = 0x1300;
p->header.type = 19;
p->header.length = sizeof(struct smbios_type_19);
p->header.handle = 0x1300;
p->starting_address = 0;
p->ending_address = (memory_size_mb-1) * 1024;
p->memory_array_handle = 0x1000;
p->partition_width = 1;
p->starting_address = 0;
p->ending_address = (memory_size_mb-1) * 1024;
p->memory_array_handle = 0x1000;
p->partition_width = 1;
start += sizeof(struct smbios_type_19);
*((uint16_t *)start) = 0;
return start + 2;
start += sizeof(struct smbios_type_19);
*((uint16_t *)start) = 0;
return start + 2;
}
/* Type 20 -- Memory Device Mapped Address */
static void *
smbios_type_20_init(void *start, uint32_t memory_size_mb)
{
struct smbios_type_20 *p = (struct smbios_type_20 *)start;
struct smbios_type_20 *p = (struct smbios_type_20 *)start;
p->header.type = 20;
p->header.length = sizeof(struct smbios_type_20);
p->header.handle = 0x1400;
p->header.type = 20;
p->header.length = sizeof(struct smbios_type_20);
p->header.handle = 0x1400;
p->starting_address = 0;
p->ending_address = (memory_size_mb-1)*1024;
p->memory_device_handle = 0x1100;
p->memory_array_mapped_address_handle = 0x1300;
p->partition_row_position = 1;
p->interleave_position = 0;
p->interleaved_data_depth = 0;
p->starting_address = 0;
p->ending_address = (memory_size_mb-1)*1024;
p->memory_device_handle = 0x1100;
p->memory_array_mapped_address_handle = 0x1300;
p->partition_row_position = 1;
p->interleave_position = 0;
p->interleaved_data_depth = 0;
start += sizeof(struct smbios_type_20);
start += sizeof(struct smbios_type_20);
*((uint16_t *)start) = 0;
return start+2;
*((uint16_t *)start) = 0;
return start+2;
}
/* Type 32 -- System Boot Information */
static void *
smbios_type_32_init(void *start)
{
struct smbios_type_32 *p = (struct smbios_type_32 *)start;
struct smbios_type_32 *p = (struct smbios_type_32 *)start;
p->header.type = 32;
p->header.length = sizeof(struct smbios_type_32);
p->header.handle = 0x2000;
memset(p->reserved, 0, 6);
p->boot_status = 0; /* no errors detected */
p->header.type = 32;
p->header.length = sizeof(struct smbios_type_32);
p->header.handle = 0x2000;
memset(p->reserved, 0, 6);
p->boot_status = 0; /* no errors detected */
start += sizeof(struct smbios_type_32);
*((uint16_t *)start) = 0;
return start+2;
start += sizeof(struct smbios_type_32);
*((uint16_t *)start) = 0;
return start+2;
}
/* Type 127 -- End of Table */
static void *
smbios_type_127_init(void *start)
{
struct smbios_type_127 *p = (struct smbios_type_127 *)start;
struct smbios_type_127 *p = (struct smbios_type_127 *)start;
p->header.type = 127;
p->header.length = sizeof(struct smbios_type_127);
p->header.handle = 0x7f00;
p->header.type = 127;
p->header.length = sizeof(struct smbios_type_127);
p->header.handle = 0x7f00;
start += sizeof(struct smbios_type_127);
*((uint16_t *)start) = 0;
return start + 2;
start += sizeof(struct smbios_type_127);
*((uint16_t *)start) = 0;
return start + 2;
}
/*
* Local variables:
* mode: C
* c-set-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/
+380 -166
View File
@@ -20,175 +20,193 @@
#include "acpi/acpi2_0.h" /* for ACPI_PHYSICAL_ADDRESS */
#include "util.h"
#include "config.h"
#include <stdint.h>
void outw(uint16_t addr, uint16_t val)
{
__asm__ __volatile__ ("outw %%ax, %%dx" :: "d"(addr), "a"(val));
}
#include <xenctrl.h>
void outb(uint16_t addr, uint8_t val)
{
__asm__ __volatile__ ("outb %%al, %%dx" :: "d"(addr), "a"(val));
__asm__ __volatile__ ( "outb %%al, %%dx" :: "d"(addr), "a"(val) );
}
void outw(uint16_t addr, uint16_t val)
{
__asm__ __volatile__ ( "outw %%ax, %%dx" :: "d"(addr), "a"(val) );
}
void outl(uint16_t addr, uint32_t val)
{
__asm__ __volatile__ ( "outl %%eax, %%dx" :: "d"(addr), "a"(val) );
}
uint8_t inb(uint16_t addr)
{
uint8_t val;
__asm__ __volatile__ ("inb %w1,%0" : "=a" (val) : "Nd" (addr));
return val;
uint8_t val;
__asm__ __volatile__ ( "inb %%dx,%%al" : "=a" (val) : "d" (addr) );
return val;
}
uint16_t inw(uint16_t addr)
{
uint16_t val;
__asm__ __volatile__ ( "inw %%dx,%%ax" : "=a" (val) : "d" (addr) );
return val;
}
uint32_t inl(uint16_t addr)
{
uint32_t val;
__asm__ __volatile__ ( "inl %%dx,%%eax" : "=a" (val) : "d" (addr) );
return val;
}
char *itoa(char *a, unsigned int i)
{
unsigned int _i = i, x = 0;
unsigned int _i = i, x = 0;
do {
x++;
_i /= 10;
} while (_i != 0);
do {
x++;
_i /= 10;
} while ( _i != 0 );
a += x;
*a-- = '\0';
a += x;
*a-- = '\0';
do {
*a-- = (i % 10) + '0';
i /= 10;
} while (i != 0);
do {
*a-- = (i % 10) + '0';
i /= 10;
} while ( i != 0 );
return a + 1;
return a + 1;
}
int strcmp(const char *cs, const char *ct)
{
signed char res;
signed char res;
while (((res = *cs - *ct++) == 0) && (*cs++ != '\0'))
continue;
while ( ((res = *cs - *ct++) == 0) && (*cs++ != '\0') )
continue;
return res;
return res;
}
void *memcpy(void *dest, const void *src, unsigned n)
{
int t0, t1, t2;
int t0, t1, t2;
__asm__ __volatile__(
"cld\n"
"rep; movsl\n"
"testb $2,%b4\n"
"je 1f\n"
"movsw\n"
"1: testb $1,%b4\n"
"je 2f\n"
"movsb\n"
"2:"
: "=&c" (t0), "=&D" (t1), "=&S" (t2)
: "0" (n/4), "q" (n), "1" ((long) dest), "2" ((long) src)
: "memory"
);
return dest;
__asm__ __volatile__ (
"cld\n"
"rep; movsl\n"
"testb $2,%b4\n"
"je 1f\n"
"movsw\n"
"1: testb $1,%b4\n"
"je 2f\n"
"movsb\n"
"2:"
: "=&c" (t0), "=&D" (t1), "=&S" (t2)
: "0" (n/4), "q" (n), "1" ((long) dest), "2" ((long) src)
: "memory" );
return dest;
}
void *memmove(void *dest, const void *src, unsigned n)
{
if ((long)dest > (long)src) {
n--;
while (n > 0) {
((char *)dest)[n] = ((char *)src)[n];
n--;
}
} else {
memcpy(dest, src, n);
}
return dest;
}
void puts(const char *s)
{
while (*s)
outb(0xE9, *s++);
if ( (long)dest > (long)src )
{
n--;
while ( n > 0 )
{
((char *)dest)[n] = ((char *)src)[n];
n--;
}
}
else
{
memcpy(dest, src, n);
}
return dest;
}
char *
strcpy(char *dest, const char *src)
{
char *p = dest;
while (*src)
*p++ = *src++;
*p = 0;
return dest;
char *p = dest;
while ( *src )
*p++ = *src++;
*p = 0;
return dest;
}
char *
strncpy(char *dest, const char *src, unsigned n)
{
int i = 0;
char *p = dest;
int i = 0;
char *p = dest;
/* write non-NUL characters from src into dest until we run
out of room in dest or encounter a NUL in src */
while (i < n && *src) {
*p++ = *src++;
++i;
}
/* write non-NUL characters from src into dest until we run
out of room in dest or encounter a NUL in src */
while ( (i < n) && *src )
{
*p++ = *src++;
i++;
}
/* pad remaining bytes of dest with NUL bytes */
while (i < n) {
*p++ = 0;
++i;
}
/* pad remaining bytes of dest with NUL bytes */
while ( i < n )
{
*p++ = 0;
i++;
}
return dest;
return dest;
}
unsigned
strlen(const char *s)
{
int i = 0;
while (*s++)
++i;
return i;
int i = 0;
while ( *s++ )
i++;
return i;
}
void *
memset(void *s, int c, unsigned n)
{
uint8_t b = (uint8_t) c;
uint8_t *p = (uint8_t *)s;
int i;
for (i = 0; i < n; ++i)
*p++ = b;
return s;
uint8_t b = (uint8_t) c;
uint8_t *p = (uint8_t *)s;
int i;
for ( i = 0; i < n; i++ )
*p++ = b;
return s;
}
int
memcmp(const void *s1, const void *s2, unsigned n)
{
unsigned i;
uint8_t *p1 = (uint8_t *) s1;
uint8_t *p2 = (uint8_t *) s2;
unsigned i;
uint8_t *p1 = (uint8_t *) s1;
uint8_t *p2 = (uint8_t *) s2;
for (i = 0; i < n; ++i) {
if (p1[i] < p2[i])
return -1;
else if (p1[i] > p2[i])
return 1;
}
for ( i = 0; i < n; i++ )
{
if ( p1[i] < p2[i] )
return -1;
else if ( p1[i] > p2[i] )
return 1;
}
return 0;
return 0;
}
void
cpuid(uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
{
__asm__ __volatile__(
"cpuid"
: "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
: "0" (idx) );
__asm__ __volatile__ (
"cpuid"
: "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
: "0" (idx) );
}
/* Write a two-character hex representation of 'byte' to digits[].
@@ -196,18 +214,18 @@ cpuid(uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
void
byte_to_hex(char *digits, uint8_t byte)
{
uint8_t nybbel = byte >> 4;
uint8_t nybbel = byte >> 4;
if (nybbel > 9)
digits[0] = 'a' + nybbel-10;
else
digits[0] = '0' + nybbel;
if ( nybbel > 9 )
digits[0] = 'a' + nybbel-10;
else
digits[0] = '0' + nybbel;
nybbel = byte & 0x0f;
if (nybbel > 9)
digits[1] = 'a' + nybbel-10;
else
digits[1] = '0' + nybbel;
nybbel = byte & 0x0f;
if ( nybbel > 9 )
digits[1] = 'a' + nybbel-10;
else
digits[1] = '0' + nybbel;
}
/* Convert an array of 16 unsigned bytes to a DCE/OSF formatted UUID
@@ -217,34 +235,39 @@ byte_to_hex(char *digits, uint8_t byte)
void
uuid_to_string(char *dest, uint8_t *uuid)
{
int i = 0;
char *p = dest;
int i = 0;
char *p = dest;
for (i = 0; i < 4; ++i) {
byte_to_hex(p, uuid[i]);
p += 2;
}
*p++ = '-';
for (i = 4; i < 6; ++i) {
byte_to_hex(p, uuid[i]);
p += 2;
}
*p++ = '-';
for (i = 6; i < 8; ++i) {
byte_to_hex(p, uuid[i]);
p += 2;
}
*p++ = '-';
for (i = 8; i < 10; ++i) {
byte_to_hex(p, uuid[i]);
p += 2;
}
*p++ = '-';
for (i = 10; i < 16; ++i) {
byte_to_hex(p, uuid[i]);
p += 2;
}
*p = 0;
for ( i = 0; i < 4; i++ )
{
byte_to_hex(p, uuid[i]);
p += 2;
}
*p++ = '-';
for ( i = 4; i < 6; i++ )
{
byte_to_hex(p, uuid[i]);
p += 2;
}
*p++ = '-';
for ( i = 6; i < 8; i++ )
{
byte_to_hex(p, uuid[i]);
p += 2;
}
*p++ = '-';
for ( i = 8; i < 10; i++ )
{
byte_to_hex(p, uuid[i]);
p += 2;
}
*p++ = '-';
for ( i = 10; i < 16; i++ )
{
byte_to_hex(p, uuid[i]);
p += 2;
}
*p = '\0';
}
#include <xen/hvm/e820.h>
@@ -252,31 +275,222 @@ uuid_to_string(char *dest, uint8_t *uuid)
#define E820_MAP ((struct e820entry *)(E820_MAP_PAGE + E820_MAP_OFFSET))
uint64_t e820_malloc(uint64_t size, uint32_t type, uint64_t mask)
{
uint64_t addr = 0;
int c = *E820_MAP_NR - 1;
struct e820entry *e820entry = (struct e820entry *)E820_MAP;
uint64_t addr = 0;
int c = *E820_MAP_NR - 1;
struct e820entry *e820entry = (struct e820entry *)E820_MAP;
while (c >= 0) {
if (e820entry[c].type == E820_RAM &&
(e820entry[c].addr & (~mask)) == 0 &&
e820entry[c].size >= size) {
addr = e820entry[c].addr;
if (e820entry[c].size != size) {
(*E820_MAP_NR)++;
memmove(&e820entry[c+1],
&e820entry[c],
(*E820_MAP_NR - c) *
sizeof(struct e820entry));
e820entry[c].size -= size;
addr += e820entry[c].size;
c++;
}
e820entry[c].addr = addr;
e820entry[c].size = size;
e820entry[c].type = type;
break;
}
c--;
}
return addr;
while ( c >= 0 )
{
if ( (e820entry[c].type == E820_RAM) &&
((e820entry[c].addr & (~mask)) == 0) &&
(e820entry[c].size >= size) )
{
addr = e820entry[c].addr;
if ( e820entry[c].size != size )
{
(*E820_MAP_NR)++;
memmove(&e820entry[c+1],
&e820entry[c],
(*E820_MAP_NR - c) *
sizeof(struct e820entry));
e820entry[c].size -= size;
addr += e820entry[c].size;
c++;
}
e820entry[c].addr = addr;
e820entry[c].size = size;
e820entry[c].type = type;
break;
}
c--;
}
return addr;
}
uint32_t ioapic_read(uint32_t reg)
{
uint32_t *ioregsel = (uint32_t *)(IOAPIC_BASE_ADDRESS + 0x00);
uint32_t *iowin = (uint32_t *)(IOAPIC_BASE_ADDRESS + 0x10);
*ioregsel = reg;
mb();
return *iowin;
}
void ioapic_write(uint32_t reg, uint32_t val)
{
uint32_t *ioregsel = (uint32_t *)(IOAPIC_BASE_ADDRESS + 0x00);
uint32_t *iowin = (uint32_t *)(IOAPIC_BASE_ADDRESS + 0x10);
*ioregsel = reg;
wmb();
*iowin = val;
}
#define PCI_CONF1_ADDRESS(bus, devfn, reg) \
(0x80000000 | (bus << 16) | (devfn << 8) | (reg & ~3))
uint32_t pci_read(uint32_t devfn, uint32_t reg, uint32_t len)
{
outl(0xcf8, PCI_CONF1_ADDRESS(0, devfn, reg));
switch ( len )
{
case 1: return inb(0xcfc + (reg & 3));
case 2: return inw(0xcfc + (reg & 2));
}
return inl(0xcfc);
}
void pci_write(uint32_t devfn, uint32_t reg, uint32_t len, uint32_t val)
{
outl(0xcf8, PCI_CONF1_ADDRESS(0, devfn, reg));
switch ( len )
{
case 1: outb(0xcfc + (reg & 3), val); break;
case 2: outw(0xcfc + (reg & 2), val); break;
case 4: outl(0xcfc, val); break;
}
}
static char *printnum(char *p, unsigned long num, int base)
{
unsigned long n;
if ( (n = num/base) > 0 )
p = printnum(p, n, base);
*p++ = "0123456789abcdef"[(int)(num % base)];
*p = '\0';
return p;
}
static void _doprint(void (*put)(char), char const *fmt, va_list ap)
{
register char *str, c;
int lflag, zflag, nflag;
char buffer[17];
unsigned value;
int i, slen, pad;
for ( ; *fmt != '\0'; fmt++ )
{
if ( *fmt != '%' )
{
put(*fmt);
continue;
}
pad = zflag = nflag = lflag = 0;
c = *++fmt;
if ( (c == '-') || isdigit(c) )
{
if ( c == '-' )
{
nflag = 1;
c = *++fmt;
}
zflag = c == '0';
for ( pad = 0; isdigit(c); c = *++fmt )
pad = (pad * 10) + c - '0';
}
if ( c == 'l' ) /* long extension */
{
lflag = 1;
c = *++fmt;
}
if ( (c == 'd') || (c == 'u') || (c == 'o') || (c == 'x') )
{
if ( lflag )
value = va_arg(ap, unsigned);
else
value = (unsigned) va_arg(ap, unsigned int);
str = buffer;
printnum(str, value,
c == 'o' ? 8 : (c == 'x' ? 16 : 10));
goto printn;
}
else if ( (c == 'O') || (c == 'D') || (c == 'X') )
{
value = va_arg(ap, unsigned);
str = buffer;
printnum(str, value,
c == 'O' ? 8 : (c == 'X' ? 16 : 10));
printn:
slen = strlen(str);
for ( i = pad - slen; i > 0; i-- )
put(zflag ? '0' : ' ');
while ( *str )
put(*str++);
}
else if ( c == 's' )
{
str = va_arg(ap, char *);
slen = strlen(str);
if ( nflag == 0 )
for ( i = pad - slen; i > 0; i-- )
put(' ');
while ( *str )
put(*str++);
if ( nflag )
for ( i = pad - slen; i > 0; i-- )
put(' ');
}
else if ( c == 'c' )
{
put(va_arg(ap, int));
}
else
{
put(*fmt);
}
}
}
static void putchar(char c)
{
outb(0xe9, c);
}
int printf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
_doprint(putchar, fmt, ap);
va_end(ap);
return 0;
}
int vprintf(const char *fmt, va_list ap)
{
_doprint(putchar, fmt, ap);
return 0;
}
void __assert_failed(char *assertion, char *file, int line)
{
printf("HVMLoader assertion '%s' failed at %s:%d\n",
assertion, file, line);
for ( ; ; )
__asm__ __volatile__ ( "ud2" );
}
void __bug(char *file, int line)
{
printf("HVMLoader bug at %s:%d\n", file, line);
for ( ; ; )
__asm__ __volatile__ ( "ud2" );
}
/*
* Local variables:
* mode: C
* c-set-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/
+29 -6
View File
@@ -1,12 +1,34 @@
#ifndef __HVMLOADER_UTIL_H__
#define __HVMLOADER_UTIL_H__
#include <stdarg.h>
extern void __assert_failed(char *assertion, char *file, int line)
__attribute__((noreturn));
#define ASSERT(p) \
do { if (!(p)) __assert_failed(#p, __FILE__, __LINE__); } while (0)
extern void __bug(char *file, int line) __attribute__((noreturn));
#define BUG() __bug()
/* I/O output */
void outb(uint16_t addr, uint8_t val);
void outw(uint16_t addr, uint16_t val);
void outb(uint16_t addr, uint8_t val);
void outl(uint16_t addr, uint32_t val);
/* I/O input */
uint8_t inb(uint16_t addr);
uint8_t inb(uint16_t addr);
uint16_t inw(uint16_t addr);
uint32_t inl(uint16_t addr);
/* PCI access */
uint32_t pci_read(uint32_t devfn, uint32_t reg, uint32_t len);
#define pci_readb(devfn, reg) ((uint8_t) pci_read(devfn, reg, 1))
#define pci_readw(devfn, reg) ((uint16_t)pci_read(devfn, reg, 2))
#define pci_readl(devfn, reg) ((uint32_t)pci_read(devfn, reg, 4))
void pci_write(uint32_t devfn, uint32_t reg, uint32_t len, uint32_t val);
#define pci_writeb(devfn, reg, val) (pci_write(devfn, reg, 1, (uint8_t) val))
#define pci_writew(devfn, reg, val) (pci_write(devfn, reg, 2, (uint16_t)val))
#define pci_writel(devfn, reg, val) (pci_write(devfn, reg, 4, (uint32_t)val))
/* Do cpuid instruction, with operation 'idx' */
void cpuid(uint32_t idx, uint32_t *eax, uint32_t *ebx,
@@ -31,15 +53,16 @@ char *itoa(char *a, unsigned int i);
void byte_to_hex(char *digits, uint8_t byte);
/* Convert an array of 16 unsigned bytes to a DCE/OSF formatted UUID
string.
Pre-condition: sizeof(dest) >= 37 */
string. Pre-condition: sizeof(dest) >= 37 */
void uuid_to_string(char *dest, uint8_t *uuid);
/* Debug output */
void puts(const char *s);
int printf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
int vprintf(const char *fmt, va_list ap);
/* Allocate region of specified type in the e820 table. */
uint64_t e820_malloc(uint64_t size, uint32_t type, uint64_t mask);
#define isdigit(c) ((c) >= '0' && (c) <= '9')
#endif /* __HVMLOADER_UTIL_H__ */
+24 -24
View File
@@ -9104,78 +9104,78 @@ pci_routing_table_structure:
db 0 ;; pci bus number
db 0x08 ;; pci device number (bit 7-3)
db 0x61 ;; link value INTA#: pointer into PCI2ISA config space
dw 0xdef8 ;; IRQ bitmap INTA#
dw 0x0c60 ;; IRQ bitmap INTA#
db 0x62 ;; link value INTB#
dw 0xdef8 ;; IRQ bitmap INTB#
dw 0x0c60 ;; IRQ bitmap INTB#
db 0x63 ;; link value INTC#
dw 0xdef8 ;; IRQ bitmap INTC#
dw 0x0c60 ;; IRQ bitmap INTC#
db 0x60 ;; link value INTD#
dw 0xdef8 ;; IRQ bitmap INTD#
dw 0x0c60 ;; IRQ bitmap INTD#
db 0 ;; physical slot (0 = embedded)
db 0 ;; reserved
;; second slot entry: 1st PCI slot
db 0 ;; pci bus number
db 0x10 ;; pci device number (bit 7-3)
db 0x62 ;; link value INTA#
dw 0xdef8 ;; IRQ bitmap INTA#
dw 0x0c60 ;; IRQ bitmap INTA#
db 0x63 ;; link value INTB#
dw 0xdef8 ;; IRQ bitmap INTB#
dw 0x0c60 ;; IRQ bitmap INTB#
db 0x60 ;; link value INTC#
dw 0xdef8 ;; IRQ bitmap INTC#
dw 0x0c60 ;; IRQ bitmap INTC#
db 0x61 ;; link value INTD#
dw 0xdef8 ;; IRQ bitmap INTD#
dw 0x0c60 ;; IRQ bitmap INTD#
db 1 ;; physical slot (0 = embedded)
db 0 ;; reserved
;; third slot entry: 2nd PCI slot
db 0 ;; pci bus number
db 0x18 ;; pci device number (bit 7-3)
db 0x63 ;; link value INTA#
dw 0xdef8 ;; IRQ bitmap INTA#
dw 0x0c60 ;; IRQ bitmap INTA#
db 0x60 ;; link value INTB#
dw 0xdef8 ;; IRQ bitmap INTB#
dw 0x0c60 ;; IRQ bitmap INTB#
db 0x61 ;; link value INTC#
dw 0xdef8 ;; IRQ bitmap INTC#
dw 0x0c60 ;; IRQ bitmap INTC#
db 0x62 ;; link value INTD#
dw 0xdef8 ;; IRQ bitmap INTD#
dw 0x0c60 ;; IRQ bitmap INTD#
db 2 ;; physical slot (0 = embedded)
db 0 ;; reserved
;; 4th slot entry: 3rd PCI slot
db 0 ;; pci bus number
db 0x20 ;; pci device number (bit 7-3)
db 0x60 ;; link value INTA#
dw 0xdef8 ;; IRQ bitmap INTA#
dw 0x0c60 ;; IRQ bitmap INTA#
db 0x61 ;; link value INTB#
dw 0xdef8 ;; IRQ bitmap INTB#
dw 0x0c60 ;; IRQ bitmap INTB#
db 0x62 ;; link value INTC#
dw 0xdef8 ;; IRQ bitmap INTC#
dw 0x0c60 ;; IRQ bitmap INTC#
db 0x63 ;; link value INTD#
dw 0xdef8 ;; IRQ bitmap INTD#
dw 0x0c60 ;; IRQ bitmap INTD#
db 3 ;; physical slot (0 = embedded)
db 0 ;; reserved
;; 5th slot entry: 4rd PCI slot
db 0 ;; pci bus number
db 0x28 ;; pci device number (bit 7-3)
db 0x61 ;; link value INTA#
dw 0xdef8 ;; IRQ bitmap INTA#
dw 0x0c60 ;; IRQ bitmap INTA#
db 0x62 ;; link value INTB#
dw 0xdef8 ;; IRQ bitmap INTB#
dw 0x0c60 ;; IRQ bitmap INTB#
db 0x63 ;; link value INTC#
dw 0xdef8 ;; IRQ bitmap INTC#
dw 0x0c60 ;; IRQ bitmap INTC#
db 0x60 ;; link value INTD#
dw 0xdef8 ;; IRQ bitmap INTD#
dw 0x0c60 ;; IRQ bitmap INTD#
db 4 ;; physical slot (0 = embedded)
db 0 ;; reserved
;; 6th slot entry: 5rd PCI slot
db 0 ;; pci bus number
db 0x30 ;; pci device number (bit 7-3)
db 0x62 ;; link value INTA#
dw 0xdef8 ;; IRQ bitmap INTA#
dw 0x0c60 ;; IRQ bitmap INTA#
db 0x63 ;; link value INTB#
dw 0xdef8 ;; IRQ bitmap INTB#
dw 0x0c60 ;; IRQ bitmap INTB#
db 0x60 ;; link value INTC#
dw 0xdef8 ;; IRQ bitmap INTC#
dw 0x0c60 ;; IRQ bitmap INTC#
db 0x61 ;; link value INTD#
dw 0xdef8 ;; IRQ bitmap INTD#
dw 0x0c60 ;; IRQ bitmap INTD#
db 5 ;; physical slot (0 = embedded)
db 0 ;; reserved
+1 -246
View File
@@ -84,12 +84,6 @@ PCIBus *i440fx_init(void)
static PCIDevice *piix3_dev;
static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
{
/* This is the barber's pole mapping used by Xen. */
return (irq_num + (pci_dev->devfn >> 3)) & 3;
}
static void piix3_write_config(PCIDevice *d,
uint32_t address, uint32_t val, int len)
{
@@ -114,12 +108,9 @@ static void piix3_reset(PCIDevice *d)
uint8_t *pci_conf = d->config;
pci_conf[0x04] = 0x07; // master, memory and I/O
pci_conf[0x05] = 0x00;
pci_conf[0x06] = 0x00;
pci_conf[0x07] = 0x02; // PCI_status_devsel_medium
pci_conf[0x4c] = 0x4d;
pci_conf[0x4e] = 0x03;
pci_conf[0x4f] = 0x00;
pci_conf[0x60] = 0x80;
pci_conf[0x61] = 0x80;
pci_conf[0x62] = 0x80;
@@ -129,22 +120,9 @@ static void piix3_reset(PCIDevice *d)
pci_conf[0x76] = 0x0c;
pci_conf[0x77] = 0x0c;
pci_conf[0x78] = 0x02;
pci_conf[0x79] = 0x00;
pci_conf[0x80] = 0x00;
pci_conf[0x82] = 0x00;
pci_conf[0xa0] = 0x08;
pci_conf[0xa0] = 0x08;
pci_conf[0xa2] = 0x00;
pci_conf[0xa3] = 0x00;
pci_conf[0xa4] = 0x00;
pci_conf[0xa5] = 0x00;
pci_conf[0xa6] = 0x00;
pci_conf[0xa7] = 0x00;
pci_conf[0xa8] = 0x0f;
pci_conf[0xaa] = 0x00;
pci_conf[0xab] = 0x00;
pci_conf[0xac] = 0x00;
pci_conf[0xae] = 0x00;
}
int piix3_init(PCIBus *bus)
@@ -171,227 +149,4 @@ int piix3_init(PCIBus *bus)
return d->devfn;
}
/***********************************************************/
/* XXX: the following should be moved to the PC BIOS */
static __attribute__((unused)) uint32_t isa_inb(uint32_t addr)
{
return cpu_inb(NULL, addr);
}
static void isa_outb(uint32_t val, uint32_t addr)
{
cpu_outb(NULL, addr, val);
}
static __attribute__((unused)) uint32_t isa_inw(uint32_t addr)
{
return cpu_inw(NULL, addr);
}
static __attribute__((unused)) void isa_outw(uint32_t val, uint32_t addr)
{
cpu_outw(NULL, addr, val);
}
static __attribute__((unused)) uint32_t isa_inl(uint32_t addr)
{
return cpu_inl(NULL, addr);
}
static __attribute__((unused)) void isa_outl(uint32_t val, uint32_t addr)
{
cpu_outl(NULL, addr, val);
}
static uint32_t pci_bios_io_addr;
static uint32_t pci_bios_mem_addr;
/* host irqs corresponding to PCI irqs A-D */
static uint8_t pci_irqs[4] = { 10, 11, 10, 11 };
static void pci_config_writel(PCIDevice *d, uint32_t addr, uint32_t val)
{
PCIBus *s = d->bus;
addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
pci_data_write(s, addr, val, 4);
}
static void pci_config_writew(PCIDevice *d, uint32_t addr, uint32_t val)
{
PCIBus *s = d->bus;
addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
pci_data_write(s, addr, val, 2);
}
static void pci_config_writeb(PCIDevice *d, uint32_t addr, uint32_t val)
{
PCIBus *s = d->bus;
addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
pci_data_write(s, addr, val, 1);
}
static __attribute__((unused)) uint32_t pci_config_readl(PCIDevice *d, uint32_t addr)
{
PCIBus *s = d->bus;
addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
return pci_data_read(s, addr, 4);
}
static uint32_t pci_config_readw(PCIDevice *d, uint32_t addr)
{
PCIBus *s = d->bus;
addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
return pci_data_read(s, addr, 2);
}
static uint32_t pci_config_readb(PCIDevice *d, uint32_t addr)
{
PCIBus *s = d->bus;
addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
return pci_data_read(s, addr, 1);
}
static void pci_set_io_region_addr(PCIDevice *d, int region_num, uint32_t addr)
{
PCIIORegion *r;
uint16_t cmd;
uint32_t ofs;
if ( region_num == PCI_ROM_SLOT ) {
ofs = 0x30;
}else{
ofs = 0x10 + region_num * 4;
}
pci_config_writel(d, ofs, addr);
r = &d->io_regions[region_num];
/* enable memory mappings */
cmd = pci_config_readw(d, PCI_COMMAND);
if ( region_num == PCI_ROM_SLOT )
cmd |= 2;
else if (r->type & PCI_ADDRESS_SPACE_IO)
cmd |= 1;
else
cmd |= 2;
pci_config_writew(d, PCI_COMMAND, cmd);
}
static void pci_bios_init_device(PCIDevice *d)
{
int class;
PCIIORegion *r;
uint32_t *paddr;
int i, pin, pic_irq, vendor_id, device_id;
class = pci_config_readw(d, PCI_CLASS_DEVICE);
vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
device_id = pci_config_readw(d, PCI_DEVICE_ID);
switch(class) {
case 0x0101:
if (vendor_id == 0x8086 && device_id == 0x7010) {
/* PIIX3 IDE */
pci_config_writew(d, 0x40, 0x8000); // enable IDE0
pci_config_writew(d, 0x42, 0x8000); // enable IDE1
goto default_map;
} else {
/* IDE: we map it as in ISA mode */
pci_set_io_region_addr(d, 0, 0x1f0);
pci_set_io_region_addr(d, 1, 0x3f4);
pci_set_io_region_addr(d, 2, 0x170);
pci_set_io_region_addr(d, 3, 0x374);
}
break;
case 0x0680:
if (vendor_id == 0x8086 && device_id == 0x7113) {
/*
* PIIX4 ACPI PM.
* Special device with special PCI config space. No ordinary BARs.
*/
pci_config_writew(d, 0x20, 0x0000); // No smb bus IO enable
pci_config_writew(d, 0x22, 0x0000);
pci_config_writew(d, 0x3c, 0x0009); // Hardcoded IRQ9
pci_config_writew(d, 0x3d, 0x0001);
}
break;
case 0x0300:
if (vendor_id != 0x1234)
goto default_map;
/* VGA: map frame buffer to default Bochs VBE address */
pci_set_io_region_addr(d, 0, 0xE0000000);
break;
case 0x0800:
/* PIC */
vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
device_id = pci_config_readw(d, PCI_DEVICE_ID);
if (vendor_id == 0x1014) {
/* IBM */
if (device_id == 0x0046 || device_id == 0xFFFF) {
/* MPIC & MPIC2 */
pci_set_io_region_addr(d, 0, 0x80800000 + 0x00040000);
}
}
break;
case 0xff00:
if (vendor_id == 0x0106b &&
(device_id == 0x0017 || device_id == 0x0022)) {
/* macio bridge */
pci_set_io_region_addr(d, 0, 0x80800000);
}
break;
default:
default_map:
/* default memory mappings */
for(i = 0; i < PCI_NUM_REGIONS; i++) {
r = &d->io_regions[i];
if (r->size) {
if (r->type & PCI_ADDRESS_SPACE_IO)
paddr = &pci_bios_io_addr;
else
paddr = &pci_bios_mem_addr;
*paddr = (*paddr + r->size - 1) & ~(r->size - 1);
pci_set_io_region_addr(d, i, *paddr);
*paddr += r->size;
}
}
break;
}
/* map the interrupt */
pin = pci_config_readb(d, PCI_INTERRUPT_PIN);
if (pin != 0) {
pin = pci_slot_get_pirq(d, pin - 1);
pic_irq = pci_irqs[pin];
pci_config_writeb(d, PCI_INTERRUPT_LINE, pic_irq);
}
}
/*
* This function initializes the PCI devices as a normal PCI BIOS
* would do. It is provided just in case the BIOS has no support for
* PCI.
*/
void pci_bios_init(void)
{
int i, irq;
uint8_t elcr[2];
pci_bios_io_addr = 0xc000;
pci_bios_mem_addr = HVM_BELOW_4G_MMIO_START;
/* activate IRQ mappings */
elcr[0] = 0x00;
elcr[1] = 0x00;
for(i = 0; i < 4; i++) {
irq = pci_irqs[i];
/* set to trigger level */
elcr[irq >> 3] |= (1 << (irq & 7));
/* activate irq remapping in PIIX */
pci_config_writeb(piix3_dev, 0x60 + i, irq);
}
isa_outb(elcr[0], 0x4d0);
isa_outb(elcr[1], 0x4d1);
pci_for_each_device(pci_bios_init_device);
}
void pci_bios_init(void) {}
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.