mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
[HVM] Move PCI and PCI-ISA bridge setup to hvmloader.
Signed-off-by: Keir Fraser <keir@xensource.com>
This commit is contained in:
1 parent
9fd9cc0666
commit
bbfa22f8c9
11 files changed
+1065
-838
No files matched your search
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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__ */
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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:
|
||||
*/
|
||||
@@ -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__ */
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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) {}
|
||||