pci, pc, acpi fixes, enhancements

This includes some pretty big changes:
 - pci master abort support by Marcel
 - pci IRQ API rework by Marcel
 - acpi generation support by myself
 
 Everything has gone through several revisions, latest versions have been on
 list for a while without any more comments, tested by several
 people.
 
 Please pull for 1.7.
 
 Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.15 (GNU/Linux)
 
 iQEcBAABAgAGBQJSXNO8AAoJECgfDbjSjVRp7VAH/0B73mCOiyVACGx7fazK3SGK
 X8TxZWVtG5A77ISqKyrtjLAhK9DCQjEzQTbMNhXHM3Ar6crwo7nJZnQvH2Gh1X2p
 34BOQSVc4rtXz5pwDIr48dBLrxeslwXub79chUs+IK1/4RSn3h3nuS3k6JVkmLJN
 rcHMj4ljJmi4Hd9vOpmS1jo/a61usi36hhU7CMgcrsXzStZycBBzCozOB3VW8p1X
 /iwyf91YjmNPkn9gA3/aViGjszu8jE91dkA0C+ljwvcGbs2yEl3LCWEJfsMvoh5P
 2M+k0XXbHwq/P9PFMa/2/lWOo4EO4Oxa+G/6QvovJrteYnktr+E9DqjU8pCT7yI=
 =CVfs
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'mst/tags/for_anthony' into staging

pci, pc, acpi fixes, enhancements

This includes some pretty big changes:
- pci master abort support by Marcel
- pci IRQ API rework by Marcel
- acpi generation support by myself

Everything has gone through several revisions, latest versions have been on
list for a while without any more comments, tested by several
people.

Please pull for 1.7.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

# gpg: Signature made Tue 15 Oct 2013 07:33:48 AM CEST using RSA key ID D28D5469
# gpg: Can't check signature: public key not found

* mst/tags/for_anthony: (39 commits)
  ssdt-proc: update generated file
  ssdt: fix PBLK length
  i386: ACPI table generation code from seabios
  pc: use new api to add builtin tables
  acpi: add interface to access user-installed tables
  hpet: add API to find it
  pvpanic: add API to access io port
  ich9: APIs for pc guest info
  piix: APIs for pc guest info
  acpi/piix: add macros for acpi property names
  i386: define pc guest info
  loader: allow adding ROMs in done callbacks
  i386: add bios linker/loader
  loader: use file path size from fw_cfg.h
  acpi: ssdt pcihp: updat generated file
  acpi: pre-compiled ASL files
  acpi: add rules to compile ASL source
  i386: add ACPI table files from seabios
  q35: expose mmcfg size as a property
  q35: use macro for MCFG property name
  ...

Message-id: 1381818560-18367-1-git-send-email-mst@redhat.com
Signed-off-by: Anthony Liguori <anthony@codemonkey.ws>
This commit is contained in:
Anthony Liguori 2013-10-31 16:58:32 +01:00
commit b0eb759fb2
95 changed files with 16666 additions and 172 deletions

9
configure vendored
View File

@ -119,6 +119,7 @@ path_of() {
# default parameters
source_path=`dirname "$0"`
cpu=""
iasl="iasl"
interp_prefix="/usr/gnemul/qemu-%M"
static="no"
cross_prefix=""
@ -257,6 +258,8 @@ for opt do
;;
--cxx=*) CXX="$optarg"
;;
--iasl=*) iasl="$optarg"
;;
--source-path=*) source_path="$optarg"
;;
--cpu=*) cpu="$optarg"
@ -1058,6 +1061,7 @@ echo "Advanced options (experts only):"
echo " --source-path=PATH path of source code [$source_path]"
echo " --cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]"
echo " --cc=CC use C compiler CC [$cc]"
echo " --iasl=IASL use ACPI compiler IASL [$iasl]"
echo " --host-cc=CC use C compiler CC [$host_cc] for code run at"
echo " build time"
echo " --cxx=CXX use C++ compiler CXX [$cxx]"
@ -4234,6 +4238,9 @@ else
fi
echo "PYTHON=$python" >> $config_host_mak
echo "CC=$cc" >> $config_host_mak
if $iasl -h > /dev/null 2>&1; then
echo "IASL=$iasl" >> $config_host_mak
fi
echo "CC_I386=$cc_i386" >> $config_host_mak
echo "HOST_CC=$host_cc" >> $config_host_mak
echo "CXX=$cxx" >> $config_host_mak
@ -4686,7 +4693,7 @@ for rom in seabios vgabios ; do
echo "BCC=bcc" >> $config_mak
echo "CPP=$cpp" >> $config_mak
echo "OBJCOPY=objcopy" >> $config_mak
echo "IASL=iasl" >> $config_mak
echo "IASL=$iasl" >> $config_mak
echo "LD=$ld" >> $config_mak
done

View File

@ -80,6 +80,10 @@ guest. This is done with memory_region_add_subregion_overlap(), which
allows the region to overlap any other region in the same container, and
specifies a priority that allows the core to decide which of two regions at
the same address are visible (highest wins).
Priority values are signed, and the default value is zero. This means that
you can use memory_region_add_subregion_overlap() both to specify a region
that must sit 'above' any others (with a positive priority) and also a
background region that sits 'below' others (with a negative priority).
Visibility
----------

View File

@ -309,6 +309,46 @@ out:
error_propagate(errp, err);
}
static bool acpi_table_builtin = false;
void acpi_table_add_builtin(const QemuOpts *opts, Error **errp)
{
acpi_table_builtin = true;
acpi_table_add(opts, errp);
}
unsigned acpi_table_len(void *current)
{
struct acpi_table_header *hdr = current - sizeof(hdr->_length);
return hdr->_length;
}
static
void *acpi_table_hdr(void *h)
{
struct acpi_table_header *hdr = h;
return &hdr->sig;
}
uint8_t *acpi_table_first(void)
{
if (acpi_table_builtin || !acpi_tables) {
return NULL;
}
return acpi_table_hdr(acpi_tables + ACPI_TABLE_PFX_SIZE);
}
uint8_t *acpi_table_next(uint8_t *current)
{
uint8_t *next = current + acpi_table_len(current);
if (next - acpi_tables >= acpi_tables_len) {
return NULL;
} else {
return acpi_table_hdr(next);
}
}
static void acpi_notify_wakeup(Notifier *notifier, void *data)
{
ACPIREGS *ar = container_of(notifier, ACPIREGS, wakeup);

View File

@ -24,6 +24,7 @@
* GNU GPL, version 2 or (at your option) any later version.
*/
#include "hw/hw.h"
#include "qapi/visitor.h"
#include "hw/i386/pc.h"
#include "hw/pci/pci.h"
#include "qemu/timer.h"
@ -228,3 +229,26 @@ void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
pm->powerdown_notifier.notify = pm_powerdown_req;
qemu_register_powerdown_notifier(&pm->powerdown_notifier);
}
static void ich9_pm_get_gpe0_blk(Object *obj, Visitor *v,
void *opaque, const char *name,
Error **errp)
{
ICH9LPCPMRegs *pm = opaque;
uint32_t value = pm->pm_io_base + ICH9_PMIO_GPE0_STS;
visit_type_uint32(v, &value, name, errp);
}
void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp)
{
static const uint32_t gpe0_len = ICH9_PMIO_GPE0_LEN;
object_property_add_uint32_ptr(obj, ACPI_PM_PROP_PM_IO_BASE,
&pm->pm_io_base, errp);
object_property_add(obj, ACPI_PM_PROP_GPE0_BLK, "uint32",
ich9_pm_get_gpe0_blk,
NULL, NULL, pm, NULL);
object_property_add_uint32_ptr(obj, ACPI_PM_PROP_GPE0_BLK_LEN,
&gpe0_len, errp);
}

View File

@ -29,6 +29,7 @@
#include "exec/ioport.h"
#include "hw/nvram/fw_cfg.h"
#include "exec/address-spaces.h"
#include "hw/acpi/piix4.h"
//#define DEBUG
@ -69,6 +70,8 @@ typedef struct PIIX4PMState {
/*< public >*/
MemoryRegion io;
uint32_t io_base;
MemoryRegion io_gpe;
MemoryRegion io_pci;
MemoryRegion io_cpu;
@ -152,14 +155,13 @@ static void apm_ctrl_changed(uint32_t val, void *arg)
static void pm_io_space_update(PIIX4PMState *s)
{
PCIDevice *d = PCI_DEVICE(s);
uint32_t pm_io_base;
pm_io_base = le32_to_cpu(*(uint32_t *)(d->config + 0x40));
pm_io_base &= 0xffc0;
s->io_base = le32_to_cpu(*(uint32_t *)(d->config + 0x40));
s->io_base &= 0xffc0;
memory_region_transaction_begin();
memory_region_set_enabled(&s->io, d->config[0x80] & 1);
memory_region_set_address(&s->io, pm_io_base);
memory_region_set_address(&s->io, s->io_base);
memory_region_transaction_commit();
}
@ -407,6 +409,28 @@ static void piix4_pm_machine_ready(Notifier *n, void *opaque)
(memory_region_present(io_as, 0x2f8) ? 0x90 : 0);
}
static void piix4_pm_add_propeties(PIIX4PMState *s)
{
static const uint8_t acpi_enable_cmd = ACPI_ENABLE;
static const uint8_t acpi_disable_cmd = ACPI_DISABLE;
static const uint32_t gpe0_blk = GPE_BASE;
static const uint32_t gpe0_blk_len = GPE_LEN;
static const uint16_t sci_int = 9;
object_property_add_uint8_ptr(OBJECT(s), ACPI_PM_PROP_ACPI_ENABLE_CMD,
&acpi_enable_cmd, NULL);
object_property_add_uint8_ptr(OBJECT(s), ACPI_PM_PROP_ACPI_DISABLE_CMD,
&acpi_disable_cmd, NULL);
object_property_add_uint32_ptr(OBJECT(s), ACPI_PM_PROP_GPE0_BLK,
&gpe0_blk, NULL);
object_property_add_uint32_ptr(OBJECT(s), ACPI_PM_PROP_GPE0_BLK_LEN,
&gpe0_blk_len, NULL);
object_property_add_uint16_ptr(OBJECT(s), ACPI_PM_PROP_SCI_INT,
&sci_int, NULL);
object_property_add_uint32_ptr(OBJECT(s), ACPI_PM_PROP_PM_IO_BASE,
&s->io_base, NULL);
}
static int piix4_pm_initfn(PCIDevice *dev)
{
PIIX4PMState *s = PIIX4_PM(dev);
@ -456,9 +480,21 @@ static int piix4_pm_initfn(PCIDevice *dev)
piix4_acpi_system_hot_add_init(pci_address_space_io(dev), dev->bus, s);
piix4_pm_add_propeties(s);
return 0;
}
Object *piix4_pm_find(void)
{
bool ambig;
Object *o = object_resolve_path_type("", TYPE_PIIX4_PM, &ambig);
if (ambig || !o) {
return NULL;
}
return o;
}
i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
qemu_irq sci_irq, qemu_irq smi_irq,
int kvm_enabled, FWCfgState *fw_cfg)
@ -489,9 +525,9 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
static Property piix4_pm_properties[] = {
DEFINE_PROP_UINT32("smb_io_base", PIIX4PMState, smb_io_base, 0),
DEFINE_PROP_UINT8("disable_s3", PIIX4PMState, disable_s3, 0),
DEFINE_PROP_UINT8("disable_s4", PIIX4PMState, disable_s4, 0),
DEFINE_PROP_UINT8("s4_val", PIIX4PMState, s4_val, 2),
DEFINE_PROP_UINT8(ACPI_PM_PROP_S3_DISABLED, PIIX4PMState, disable_s3, 0),
DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_DISABLED, PIIX4PMState, disable_s4, 0),
DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_VAL, PIIX4PMState, s4_val, 2),
DEFINE_PROP_END_OF_LIST(),
};

View File

@ -280,12 +280,12 @@ static void update_sr (AC97LinkState *s, AC97BusMasterRegs *r, uint32_t new_sr)
if (level) {
s->glob_sta |= masks[r - s->bm_regs];
dolog ("set irq level=1\n");
qemu_set_irq (s->dev.irq[0], 1);
pci_irq_assert(&s->dev);
}
else {
s->glob_sta &= ~masks[r - s->bm_regs];
dolog ("set irq level=0\n");
qemu_set_irq (s->dev.irq[0], 0);
pci_irq_deassert(&s->dev);
}
}

View File

@ -323,7 +323,7 @@ static void es1370_update_status (ES1370State *s, uint32_t new_status)
else {
s->status = new_status & ~STAT_INTR;
}
qemu_set_irq (s->dev.irq[0], !!level);
pci_set_irq(&s->dev, !!level);
}
static void es1370_reset (ES1370State *s)
@ -349,7 +349,7 @@ static void es1370_reset (ES1370State *s)
s->dac_voice[i] = NULL;
}
}
qemu_irq_lower (s->dev.irq[0]);
pci_irq_deassert(&s->dev);
}
static void es1370_maybe_lower_irq (ES1370State *s, uint32_t sctl)

View File

@ -269,7 +269,7 @@ static void intel_hda_update_irq(IntelHDAState *d)
msi_notify(&d->pci, 0);
}
} else {
qemu_set_irq(d->pci.irq[0], level);
pci_set_irq(&d->pci, level);
}
}

View File

@ -69,7 +69,7 @@ static void nvme_isr_notify(NvmeCtrl *n, NvmeCQueue *cq)
if (msix_enabled(&(n->parent_obj))) {
msix_notify(&(n->parent_obj), cq->vector);
} else {
qemu_irq_pulse(n->parent_obj.irq[0]);
pci_irq_pulse(&n->parent_obj);
}
}
}

View File

@ -61,7 +61,7 @@ static int serial_pci_init(PCIDevice *dev)
}
pci->dev.config[PCI_INTERRUPT_PIN] = 0x01;
s->irq = pci->dev.irq[0];
s->irq = pci_allocate_irq(&pci->dev);
memory_region_init_io(&s->io, OBJECT(pci), &serial_io_ops, s, "serial", 8);
pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io);
@ -79,7 +79,7 @@ static void multi_serial_irq_mux(void *opaque, int n, int level)
pending = 1;
}
}
qemu_set_irq(pci->dev.irq[0], pending);
pci_set_irq(&pci->dev, pending);
}
static int multi_serial_pci_init(PCIDevice *dev)
@ -132,6 +132,7 @@ static void serial_pci_exit(PCIDevice *dev)
serial_exit_core(s);
memory_region_destroy(&s->io);
qemu_free_irq(s->irq);
}
static void multi_serial_pci_exit(PCIDevice *dev)

View File

@ -134,8 +134,8 @@ static void tpci200_set_irq(void *opaque, int intno, int level)
/* Check if the interrupt is edge sensitive */
if (dev->ctrl[ip_n] & CTRL_INT_EDGE(intno)) {
if (level) {
qemu_set_irq(dev->dev.irq[0], !dev->int_set);
qemu_set_irq(dev->dev.irq[0], dev->int_set);
pci_set_irq(&dev->dev, !dev->int_set);
pci_set_irq(&dev->dev, dev->int_set);
}
} else {
unsigned i, j;
@ -153,10 +153,10 @@ static void tpci200_set_irq(void *opaque, int intno, int level)
}
if (level_status && !dev->int_set) {
qemu_irq_raise(dev->dev.irq[0]);
pci_irq_assert(&dev->dev);
dev->int_set = 1;
} else if (!level_status && dev->int_set) {
qemu_irq_lower(dev->dev.irq[0]);
pci_irq_deassert(&dev->dev);
dev->int_set = 0;
}
}

View File

@ -68,6 +68,17 @@ qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n)
return qemu_extend_irqs(NULL, 0, handler, opaque, n);
}
qemu_irq qemu_allocate_irq(qemu_irq_handler handler, void *opaque, int n)
{
struct IRQState *irq;
irq = g_new(struct IRQState, 1);
irq->handler = handler;
irq->opaque = opaque;
irq->n = n;
return irq;
}
void qemu_free_irqs(qemu_irq *s)
{
@ -75,6 +86,11 @@ void qemu_free_irqs(qemu_irq *s)
g_free(s);
}
void qemu_free_irq(qemu_irq irq)
{
g_free(irq);
}
static void qemu_notirq(void *opaque, int line, int level)
{
struct IRQState *irq = opaque;

View File

@ -663,7 +663,7 @@ int rom_add_file(const char *file, const char *fw_dir,
rom_insert(rom);
if (rom->fw_file && fw_cfg) {
const char *basename;
char fw_file_name[56];
char fw_file_name[FW_CFG_MAX_FILE_PATH];
void *data;
basename = strrchr(rom->fw_file, '/');
@ -700,10 +700,12 @@ err:
return -1;
}
int rom_add_blob(const char *name, const void *blob, size_t len,
hwaddr addr)
void *rom_add_blob(const char *name, const void *blob, size_t len,
hwaddr addr, const char *fw_file_name,
FWCfgReadCallback fw_callback, void *callback_opaque)
{
Rom *rom;
void *data = NULL;
rom = g_malloc0(sizeof(*rom));
rom->name = g_strdup(name);
@ -713,7 +715,22 @@ int rom_add_blob(const char *name, const void *blob, size_t len,
rom->data = g_malloc0(rom->datasize);
memcpy(rom->data, blob, len);
rom_insert(rom);
return 0;
if (fw_file_name && fw_cfg) {
char devpath[100];
snprintf(devpath, sizeof(devpath), "/rom@%s", fw_file_name);
if (rom_file_in_ram) {
data = rom_set_mr(rom, OBJECT(fw_cfg), devpath);
} else {
data = rom->data;
}
fw_cfg_add_file_callback(fw_cfg, fw_file_name,
fw_callback, callback_opaque,
data, rom->romsize);
}
return data;
}
/* This function is specific for elf program because we don't need to allocate
@ -795,10 +812,14 @@ int rom_load_all(void)
memory_region_unref(section.mr);
}
qemu_register_reset(rom_reset, NULL);
roms_loaded = 1;
return 0;
}
void rom_load_done(void)
{
roms_loaded = 1;
}
void rom_set_fw(FWCfgState *f)
{
fw_cfg = f;

View File

@ -49,7 +49,7 @@ void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq)
}
static void sysbus_mmio_map_common(SysBusDevice *dev, int n, hwaddr addr,
bool may_overlap, unsigned priority)
bool may_overlap, int priority)
{
assert(n >= 0 && n < dev->num_mmio);
@ -81,7 +81,7 @@ void sysbus_mmio_map(SysBusDevice *dev, int n, hwaddr addr)
}
void sysbus_mmio_map_overlap(SysBusDevice *dev, int n, hwaddr addr,
unsigned priority)
int priority)
{
sysbus_mmio_map_common(dev, n, addr, true, priority);
}

View File

@ -1101,7 +1101,7 @@ static void qxl_update_irq(PCIQXLDevice *d)
uint32_t pending = le32_to_cpu(d->ram->int_pending);
uint32_t mask = le32_to_cpu(d->ram->int_mask);
int level = !!(pending & mask);
qemu_set_irq(d->pci.irq[0], level);
pci_set_irq(&d->pci, level);
qxl_ring_set_dirty(d);
}

View File

@ -5,3 +5,30 @@ obj-y += pc_sysfw.o
obj-$(CONFIG_XEN) += xen_domainbuild.o xen_machine_pv.o
obj-y += kvmvapic.o
obj-y += acpi-build.o
obj-y += bios-linker-loader.o
hw/i386/acpi-build.o: hw/i386/acpi-build.c hw/i386/acpi-dsdt.hex \
hw/i386/ssdt-proc.hex hw/i386/ssdt-pcihp.hex hw/i386/ssdt-misc.hex \
hw/i386/acpi-dsdt.hex hw/i386/q35-acpi-dsdt.hex
iasl-option=$(shell if test -z "`$(1) $(2) 2>&1 > /dev/null`" \
; then echo "$(2)"; else echo "$(3)"; fi ;)
ifdef IASL
#IASL Present. Generate hex files from .dsl
hw/i386/%.hex: $(SRC_PATH)/hw/i386/%.dsl $(SRC_PATH)/scripts/acpi_extract_preprocess.py $(SRC_PATH)/scripts/acpi_extract.py
$(call quiet-command, cpp -P $< -o $*.dsl.i.orig, " CPP $(TARGET_DIR)$*.dsl.i.orig")
$(call quiet-command, $(PYTHON) $(SRC_PATH)/scripts/acpi_extract_preprocess.py $*.dsl.i.orig > $*.dsl.i, " ACPI_PREPROCESS $(TARGET_DIR)$*.dsl.i")
$(call quiet-command, $(IASL) $(call iasl-option,$(IASL),-Pn,) -vs -l -tc -p $* $*.dsl.i $(if $(V), , > /dev/null) 2>&1 ," IASL $(TARGET_DIR)$*.dsl.i")
$(call quiet-command, $(SRC_PATH)/scripts/acpi_extract.py $*.lst > $*.off, " ACPI_EXTRACT $(TARGET_DIR)$*.off")
$(call quiet-command, cat $*.off > $@, " CAT $(TARGET_DIR)$@")
else
#IASL Not present. Restore pre-generated hex files.
hw/i386/%.hex: $(SRC_PATH)/hw/i386/%.hex.generated
$(call quiet-command, cp -f $< $@, " CP $(TARGET_DIR)$@")
endif
.PHONY: cleanhex
cleanhex:
rm -f hw/i386/*hex
clean: cleanhex

1214
hw/i386/acpi-build.c Normal file

File diff suppressed because it is too large Load Diff

9
hw/i386/acpi-build.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef HW_I386_ACPI_BUILD_H
#define HW_I386_ACPI_BUILD_H
#include "qemu/typedefs.h"
void acpi_setup(PcGuestInfo *);
#endif

331
hw/i386/acpi-defs.h Normal file
View File

@ -0,0 +1,331 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef QEMU_ACPI_DEFS_H
#define QEMU_ACPI_DEFS_H
enum {
ACPI_FADT_F_WBINVD,
ACPI_FADT_F_WBINVD_FLUSH,
ACPI_FADT_F_PROC_C1,
ACPI_FADT_F_P_LVL2_UP,
ACPI_FADT_F_PWR_BUTTON,
ACPI_FADT_F_SLP_BUTTON,
ACPI_FADT_F_FIX_RTC,
ACPI_FADT_F_RTC_S4,
ACPI_FADT_F_TMR_VAL_EXT,
ACPI_FADT_F_DCK_CAP,
ACPI_FADT_F_RESET_REG_SUP,
ACPI_FADT_F_SEALED_CASE,
ACPI_FADT_F_HEADLESS,
ACPI_FADT_F_CPU_SW_SLP,
ACPI_FADT_F_PCI_EXP_WAK,
ACPI_FADT_F_USE_PLATFORM_CLOCK,
ACPI_FADT_F_S4_RTC_STS_VALID,
ACPI_FADT_F_REMOTE_POWER_ON_CAPABLE,
ACPI_FADT_F_FORCE_APIC_CLUSTER_MODEL,
ACPI_FADT_F_FORCE_APIC_PHYSICAL_DESTINATION_MODE,
ACPI_FADT_F_HW_REDUCED_ACPI,
ACPI_FADT_F_LOW_POWER_S0_IDLE_CAPABLE,
};
/*
* ACPI 2.0 Generic Address Space definition.
*/
struct Acpi20GenericAddress {
uint8_t address_space_id;
uint8_t register_bit_width;
uint8_t register_bit_offset;
uint8_t reserved;
uint64_t address;
} QEMU_PACKED;
typedef struct Acpi20GenericAddress Acpi20GenericAddress;
#define ACPI_RSDP_SIGNATURE 0x2052545020445352LL // "RSD PTR "
struct AcpiRsdpDescriptor { /* Root System Descriptor Pointer */
uint64_t signature; /* ACPI signature, contains "RSD PTR " */
uint8_t checksum; /* To make sum of struct == 0 */
uint8_t oem_id [6]; /* OEM identification */
uint8_t revision; /* Must be 0 for 1.0, 2 for 2.0 */
uint32_t rsdt_physical_address; /* 32-bit physical address of RSDT */
uint32_t length; /* XSDT Length in bytes including hdr */
uint64_t xsdt_physical_address; /* 64-bit physical address of XSDT */
uint8_t extended_checksum; /* Checksum of entire table */
uint8_t reserved [3]; /* Reserved field must be 0 */
} QEMU_PACKED;
typedef struct AcpiRsdpDescriptor AcpiRsdpDescriptor;
/* Table structure from Linux kernel (the ACPI tables are under the
BSD license) */
#define ACPI_TABLE_HEADER_DEF /* ACPI common table header */ \
uint32_t signature; /* ACPI signature (4 ASCII characters) */ \
uint32_t length; /* Length of table, in bytes, including header */ \
uint8_t revision; /* ACPI Specification minor version # */ \
uint8_t checksum; /* To make sum of entire table == 0 */ \
uint8_t oem_id [6]; /* OEM identification */ \
uint8_t oem_table_id [8]; /* OEM table identification */ \
uint32_t oem_revision; /* OEM revision number */ \
uint8_t asl_compiler_id [4]; /* ASL compiler vendor ID */ \
uint32_t asl_compiler_revision; /* ASL compiler revision number */
struct AcpiTableHeader /* ACPI common table header */
{
ACPI_TABLE_HEADER_DEF
} QEMU_PACKED;
typedef struct AcpiTableHeader AcpiTableHeader;
/*
* ACPI 1.0 Fixed ACPI Description Table (FADT)
*/
#define ACPI_FACP_SIGNATURE 0x50434146 // FACP
struct AcpiFadtDescriptorRev1
{
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
uint32_t firmware_ctrl; /* Physical address of FACS */
uint32_t dsdt; /* Physical address of DSDT */
uint8_t model; /* System Interrupt Model */
uint8_t reserved1; /* Reserved */
uint16_t sci_int; /* System vector of SCI interrupt */
uint32_t smi_cmd; /* Port address of SMI command port */
uint8_t acpi_enable; /* Value to write to smi_cmd to enable ACPI */
uint8_t acpi_disable; /* Value to write to smi_cmd to disable ACPI */
uint8_t S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */
uint8_t reserved2; /* Reserved - must be zero */
uint32_t pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */
uint32_t pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */
uint32_t pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */
uint32_t pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */
uint32_t pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */
uint32_t pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */
uint32_t gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */
uint32_t gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */
uint8_t pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */
uint8_t pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */
uint8_t pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */
uint8_t pm_tmr_len; /* Byte Length of ports at pm_tm_blk */
uint8_t gpe0_blk_len; /* Byte Length of ports at gpe0_blk */
uint8_t gpe1_blk_len; /* Byte Length of ports at gpe1_blk */
uint8_t gpe1_base; /* Offset in gpe model where gpe1 events start */
uint8_t reserved3; /* Reserved */
uint16_t plvl2_lat; /* Worst case HW latency to enter/exit C2 state */
uint16_t plvl3_lat; /* Worst case HW latency to enter/exit C3 state */
uint16_t flush_size; /* Size of area read to flush caches */
uint16_t flush_stride; /* Stride used in flushing caches */
uint8_t duty_offset; /* Bit location of duty cycle field in p_cnt reg */
uint8_t duty_width; /* Bit width of duty cycle field in p_cnt reg */
uint8_t day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */
uint8_t mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */
uint8_t century; /* Index to century in RTC CMOS RAM */
uint8_t reserved4; /* Reserved */
uint8_t reserved4a; /* Reserved */
uint8_t reserved4b; /* Reserved */
uint32_t flags;
} QEMU_PACKED;
typedef struct AcpiFadtDescriptorRev1 AcpiFadtDescriptorRev1;
/*
* ACPI 1.0 Root System Description Table (RSDT)
*/
#define ACPI_RSDT_SIGNATURE 0x54445352 // RSDT
struct AcpiRsdtDescriptorRev1
{
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
uint32_t table_offset_entry[0]; /* Array of pointers to other */
/* ACPI tables */
} QEMU_PACKED;
typedef struct AcpiRsdtDescriptorRev1 AcpiRsdtDescriptorRev1;
/*
* ACPI 1.0 Firmware ACPI Control Structure (FACS)
*/
#define ACPI_FACS_SIGNATURE 0x53434146 // FACS
struct AcpiFacsDescriptorRev1
{
uint32_t signature; /* ACPI Signature */
uint32_t length; /* Length of structure, in bytes */
uint32_t hardware_signature; /* Hardware configuration signature */
uint32_t firmware_waking_vector; /* ACPI OS waking vector */
uint32_t global_lock; /* Global Lock */
uint32_t flags;
uint8_t resverved3 [40]; /* Reserved - must be zero */
} QEMU_PACKED;
typedef struct AcpiFacsDescriptorRev1 AcpiFacsDescriptorRev1;
/*
* Differentiated System Description Table (DSDT)
*/
#define ACPI_DSDT_SIGNATURE 0x54445344 // DSDT
/*
* MADT values and structures
*/
/* Values for MADT PCATCompat */
#define ACPI_DUAL_PIC 0
#define ACPI_MULTIPLE_APIC 1
/* Master MADT */
#define ACPI_APIC_SIGNATURE 0x43495041 // APIC
struct AcpiMultipleApicTable
{
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
uint32_t local_apic_address; /* Physical address of local APIC */
uint32_t flags;
} QEMU_PACKED;
typedef struct AcpiMultipleApicTable AcpiMultipleApicTable;
/* Values for Type in APIC sub-headers */
#define ACPI_APIC_PROCESSOR 0
#define ACPI_APIC_IO 1
#define ACPI_APIC_XRUPT_OVERRIDE 2
#define ACPI_APIC_NMI 3
#define ACPI_APIC_LOCAL_NMI 4
#define ACPI_APIC_ADDRESS_OVERRIDE 5
#define ACPI_APIC_IO_SAPIC 6
#define ACPI_APIC_LOCAL_SAPIC 7
#define ACPI_APIC_XRUPT_SOURCE 8
#define ACPI_APIC_RESERVED 9 /* 9 and greater are reserved */
/*
* MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
*/
#define ACPI_SUB_HEADER_DEF /* Common ACPI sub-structure header */\
uint8_t type; \
uint8_t length;
/* Sub-structures for MADT */
struct AcpiMadtProcessorApic
{
ACPI_SUB_HEADER_DEF
uint8_t processor_id; /* ACPI processor id */
uint8_t local_apic_id; /* Processor's local APIC id */
uint32_t flags;
} QEMU_PACKED;
typedef struct AcpiMadtProcessorApic AcpiMadtProcessorApic;
struct AcpiMadtIoApic
{
ACPI_SUB_HEADER_DEF
uint8_t io_apic_id; /* I/O APIC ID */
uint8_t reserved; /* Reserved - must be zero */
uint32_t address; /* APIC physical address */
uint32_t interrupt; /* Global system interrupt where INTI
* lines start */
} QEMU_PACKED;
typedef struct AcpiMadtIoApic AcpiMadtIoApic;
struct AcpiMadtIntsrcovr {
ACPI_SUB_HEADER_DEF
uint8_t bus;
uint8_t source;
uint32_t gsi;
uint16_t flags;
} QEMU_PACKED;
typedef struct AcpiMadtIntsrcovr AcpiMadtIntsrcovr;
struct AcpiMadtLocalNmi {
ACPI_SUB_HEADER_DEF
uint8_t processor_id; /* ACPI processor id */
uint16_t flags; /* MPS INTI flags */
uint8_t lint; /* Local APIC LINT# */
} QEMU_PACKED;
typedef struct AcpiMadtLocalNmi AcpiMadtLocalNmi;
/*
* HPET Description Table
*/
#define ACPI_HPET_SIGNATURE 0x54455048 // HPET
struct Acpi20Hpet {
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
uint32_t timer_block_id;
Acpi20GenericAddress addr;
uint8_t hpet_number;
uint16_t min_tick;
uint8_t page_protect;
} QEMU_PACKED;
typedef struct Acpi20Hpet Acpi20Hpet;
/*
* SRAT (NUMA topology description) table
*/
#define ACPI_SRAT_SIGNATURE 0x54415253 // SRAT
struct AcpiSystemResourceAffinityTable
{
ACPI_TABLE_HEADER_DEF
uint32_t reserved1;
uint32_t reserved2[2];
} QEMU_PACKED;
typedef struct AcpiSystemResourceAffinityTable AcpiSystemResourceAffinityTable;
#define ACPI_SRAT_PROCESSOR 0
#define ACPI_SRAT_MEMORY 1
struct AcpiSratProcessorAffinity
{
ACPI_SUB_HEADER_DEF
uint8_t proximity_lo;
uint8_t local_apic_id;
uint32_t flags;
uint8_t local_sapic_eid;
uint8_t proximity_hi[3];
uint32_t reserved;
} QEMU_PACKED;
typedef struct AcpiSratProcessorAffinity AcpiSratProcessorAffinity;
struct AcpiSratMemoryAffinity
{
ACPI_SUB_HEADER_DEF
uint8_t proximity[4];
uint16_t reserved1;
uint64_t base_addr;
uint64_t range_length;
uint32_t reserved2;
uint32_t flags;
uint32_t reserved3[2];
} QEMU_PACKED;
typedef struct AcpiSratMemoryAffinity AcpiSratMemoryAffinity;
/* PCI fw r3.0 MCFG table. */
/* Subtable */
struct AcpiMcfgAllocation {
uint64_t address; /* Base address, processor-relative */
uint16_t pci_segment; /* PCI segment group number */
uint8_t start_bus_number; /* Starting PCI Bus number */
uint8_t end_bus_number; /* Final PCI Bus number */
uint32_t reserved;
} QEMU_PACKED;
typedef struct AcpiMcfgAllocation AcpiMcfgAllocation;
#define ACPI_MCFG_SIGNATURE 0x4746434d // MCFG
/* Reserved signature: ignored by OSPM */
#define ACPI_RSRV_SIGNATURE 0x554d4551 // QEMU
struct AcpiTableMcfg {
ACPI_TABLE_HEADER_DEF;
uint8_t reserved[8];
AcpiMcfgAllocation allocation[0];
} QEMU_PACKED;
typedef struct AcpiTableMcfg AcpiTableMcfg;
#endif

View File

@ -0,0 +1,93 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/****************************************************************
* CPU hotplug
****************************************************************/
Scope(\_SB) {
/* Objects filled in by run-time generated SSDT */
External(NTFY, MethodObj)
External(CPON, PkgObj)
/* Methods called by run-time generated SSDT Processor objects */
Method(CPMA, 1, NotSerialized) {
// _MAT method - create an madt apic buffer
// Arg0 = Processor ID = Local APIC ID
// Local0 = CPON flag for this cpu
Store(DerefOf(Index(CPON, Arg0)), Local0)
// Local1 = Buffer (in madt apic form) to return
Store(Buffer(8) {0x00, 0x08, 0x00, 0x00, 0x00, 0, 0, 0}, Local1)
// Update the processor id, lapic id, and enable/disable status
Store(Arg0, Index(Local1, 2))
Store(Arg0, Index(Local1, 3))
Store(Local0, Index(Local1, 4))
Return (Local1)
}
Method(CPST, 1, NotSerialized) {
// _STA method - return ON status of cpu
// Arg0 = Processor ID = Local APIC ID
// Local0 = CPON flag for this cpu
Store(DerefOf(Index(CPON, Arg0)), Local0)
If (Local0) {
Return (0xF)
} Else {
Return (0x0)
}
}
Method(CPEJ, 2, NotSerialized) {
// _EJ0 method - eject callback
Sleep(200)
}
/* CPU hotplug notify method */
OperationRegion(PRST, SystemIO, 0xaf00, 32)
Field(PRST, ByteAcc, NoLock, Preserve) {
PRS, 256
}
Method(PRSC, 0) {
// Local5 = active cpu bitmap
Store(PRS, Local5)
// Local2 = last read byte from bitmap
Store(Zero, Local2)
// Local0 = Processor ID / APIC ID iterator
Store(Zero, Local0)
While (LLess(Local0, SizeOf(CPON))) {
// Local1 = CPON flag for this cpu
Store(DerefOf(Index(CPON, Local0)), Local1)
If (And(Local0, 0x07)) {
// Shift down previously read bitmap byte
ShiftRight(Local2, 1, Local2)
} Else {
// Read next byte from cpu bitmap
Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
}
// Local3 = active state for this cpu
Store(And(Local2, 1), Local3)
If (LNotEqual(Local1, Local3)) {
// State change - update CPON with new state
Store(Local3, Index(CPON, Local0))
// Do CPU notify
If (LEqual(Local3, 1)) {
NTFY(Local0, 1)
} Else {
NTFY(Local0, 3)
}
}
Increment(Local0)
}
}
}

View File

@ -0,0 +1,41 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/****************************************************************
* Debugging
****************************************************************/
Scope(\) {
/* Debug Output */
OperationRegion(DBG, SystemIO, 0x0402, 0x01)
Field(DBG, ByteAcc, NoLock, Preserve) {
DBGB, 8,
}
/* Debug method - use this method to send output to the QEMU
* BIOS debug port. This method handles strings, integers,
* and buffers. For example: DBUG("abc") DBUG(0x123) */
Method(DBUG, 1) {
ToHexString(Arg0, Local0)
ToBuffer(Local0, Local0)
Subtract(SizeOf(Local0), 1, Local1)
Store(Zero, Local2)
While (LLess(Local2, Local1)) {
Store(DerefOf(Index(Local0, Local2)), DBGB)
Increment(Local2)
}
Store(0x0A, DBGB)
}
}

View File

@ -0,0 +1,51 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/****************************************************************
* HPET
****************************************************************/
Scope(\_SB) {
Device(HPET) {
Name(_HID, EISAID("PNP0103"))
Name(_UID, 0)
OperationRegion(HPTM, SystemMemory, 0xFED00000, 0x400)
Field(HPTM, DWordAcc, Lock, Preserve) {
VEND, 32,
PRD, 32,
}
Method(_STA, 0, NotSerialized) {
Store(VEND, Local0)
Store(PRD, Local1)
ShiftRight(Local0, 16, Local0)
If (LOr(LEqual(Local0, 0), LEqual(Local0, 0xffff))) {
Return (0x0)
}
If (LOr(LEqual(Local1, 0), LGreater(Local1, 100000000))) {
Return (0x0)
}
Return (0x0F)
}
Name(_CRS, ResourceTemplate() {
#if 0 /* This makes WinXP BSOD for not yet figured reasons. */
IRQNoFlags() {2, 8}
#endif
Memory32Fixed(ReadOnly,
0xFED00000, // Address Base
0x00000400, // Address Length
)
})
}
}

117
hw/i386/acpi-dsdt-isa.dsl Normal file
View File

@ -0,0 +1,117 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/* Common legacy ISA style devices. */
Scope(\_SB.PCI0.ISA) {
Device(RTC) {
Name(_HID, EisaId("PNP0B00"))
Name(_CRS, ResourceTemplate() {
IO(Decode16, 0x0070, 0x0070, 0x10, 0x02)
IRQNoFlags() { 8 }
IO(Decode16, 0x0072, 0x0072, 0x02, 0x06)
})
}
Device(KBD) {
Name(_HID, EisaId("PNP0303"))
Method(_STA, 0, NotSerialized) {
Return (0x0f)
}
Name(_CRS, ResourceTemplate() {
IO(Decode16, 0x0060, 0x0060, 0x01, 0x01)
IO(Decode16, 0x0064, 0x0064, 0x01, 0x01)
IRQNoFlags() { 1 }
})
}
Device(MOU) {
Name(_HID, EisaId("PNP0F13"))
Method(_STA, 0, NotSerialized) {
Return (0x0f)
}
Name(_CRS, ResourceTemplate() {
IRQNoFlags() { 12 }
})
}
Device(FDC0) {
Name(_HID, EisaId("PNP0700"))
Method(_STA, 0, NotSerialized) {
Store(FDEN, Local0)
If (LEqual(Local0, 0)) {
Return (0x00)
} Else {
Return (0x0F)
}
}
Name(_CRS, ResourceTemplate() {
IO(Decode16, 0x03F2, 0x03F2, 0x00, 0x04)
IO(Decode16, 0x03F7, 0x03F7, 0x00, 0x01)
IRQNoFlags() { 6 }
DMA(Compatibility, NotBusMaster, Transfer8) { 2 }
})
}
Device(LPT) {
Name(_HID, EisaId("PNP0400"))
Method(_STA, 0, NotSerialized) {
Store(LPEN, Local0)
If (LEqual(Local0, 0)) {
Return (0x00)
} Else {
Return (0x0F)
}
}
Name(_CRS, ResourceTemplate() {
IO(Decode16, 0x0378, 0x0378, 0x08, 0x08)
IRQNoFlags() { 7 }
})
}
Device(COM1) {
Name(_HID, EisaId("PNP0501"))
Name(_UID, 0x01)
Method(_STA, 0, NotSerialized) {
Store(CAEN, Local0)
If (LEqual(Local0, 0)) {
Return (0x00)
} Else {
Return (0x0F)
}
}
Name(_CRS, ResourceTemplate() {
IO(Decode16, 0x03F8, 0x03F8, 0x00, 0x08)
IRQNoFlags() { 4 }
})
}
Device(COM2) {
Name(_HID, EisaId("PNP0501"))
Name(_UID, 0x02)
Method(_STA, 0, NotSerialized) {
Store(CBEN, Local0)
If (LEqual(Local0, 0)) {
Return (0x00)
} Else {
Return (0x0F)
}
}
Name(_CRS, ResourceTemplate() {
IO(Decode16, 0x02F8, 0x02F8, 0x00, 0x08)
IRQNoFlags() { 3 }
})
}
}

View File

@ -0,0 +1,105 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/* PCI CRS (current resources) definition. */
Scope(\_SB.PCI0) {
Name(CRES, ResourceTemplate() {
WordBusNumber(ResourceProducer, MinFixed, MaxFixed, PosDecode,
0x0000, // Address Space Granularity
0x0000, // Address Range Minimum
0x00FF, // Address Range Maximum
0x0000, // Address Translation Offset
0x0100, // Address Length
,, )
IO(Decode16,
0x0CF8, // Address Range Minimum
0x0CF8, // Address Range Maximum
0x01, // Address Alignment
0x08, // Address Length
)
WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
0x0000, // Address Space Granularity
0x0000, // Address Range Minimum
0x0CF7, // Address Range Maximum
0x0000, // Address Translation Offset
0x0CF8, // Address Length
,, , TypeStatic)
WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
0x0000, // Address Space Granularity
0x0D00, // Address Range Minimum
0xFFFF, // Address Range Maximum
0x0000, // Address Translation Offset
0xF300, // Address Length
,, , TypeStatic)
DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
0x00000000, // Address Space Granularity
0x000A0000, // Address Range Minimum
0x000BFFFF, // Address Range Maximum
0x00000000, // Address Translation Offset
0x00020000, // Address Length
,, , AddressRangeMemory, TypeStatic)
DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
0x00000000, // Address Space Granularity
0xE0000000, // Address Range Minimum
0xFEBFFFFF, // Address Range Maximum
0x00000000, // Address Translation Offset
0x1EC00000, // Address Length
,, PW32, AddressRangeMemory, TypeStatic)
})
Name(CR64, ResourceTemplate() {
QWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
0x00000000, // Address Space Granularity
0x8000000000, // Address Range Minimum
0xFFFFFFFFFF, // Address Range Maximum
0x00000000, // Address Translation Offset
0x8000000000, // Address Length
,, PW64, AddressRangeMemory, TypeStatic)
})
Method(_CRS, 0) {
/* Fields provided by dynamically created ssdt */
External(P0S, IntObj)
External(P0E, IntObj)
External(P1V, IntObj)
External(P1S, BuffObj)
External(P1E, BuffObj)
External(P1L, BuffObj)
/* fixup 32bit pci io window */
CreateDWordField(CRES, \_SB.PCI0.PW32._MIN, PS32)
CreateDWordField(CRES, \_SB.PCI0.PW32._MAX, PE32)
CreateDWordField(CRES, \_SB.PCI0.PW32._LEN, PL32)
Store(P0S, PS32)
Store(P0E, PE32)
Store(Add(Subtract(P0E, P0S), 1), PL32)
If (LEqual(P1V, Zero)) {
Return (CRES)
}
/* fixup 64bit pci io window */
CreateQWordField(CR64, \_SB.PCI0.PW64._MIN, PS64)
CreateQWordField(CR64, \_SB.PCI0.PW64._MAX, PE64)
CreateQWordField(CR64, \_SB.PCI0.PW64._LEN, PL64)
Store(P1S, PS64)
Store(P1E, PE64)
Store(P1L, PL64)
/* add window and return result */
ConcatenateResTemplate(CRES, CR64, Local0)
Return (Local0)
}
}

343
hw/i386/acpi-dsdt.dsl Normal file
View File

@ -0,0 +1,343 @@
/*
* Bochs/QEMU ACPI DSDT ASL definition
*
* Copyright (c) 2006 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
ACPI_EXTRACT_ALL_CODE AcpiDsdtAmlCode
DefinitionBlock (
"acpi-dsdt.aml", // Output Filename
"DSDT", // Signature
0x01, // DSDT Compliance Revision
"BXPC", // OEMID
"BXDSDT", // TABLE ID
0x1 // OEM Revision
)
{
#include "acpi-dsdt-dbug.dsl"
/****************************************************************
* PCI Bus definition
****************************************************************/
Scope(\_SB) {
Device(PCI0) {
Name(_HID, EisaId("PNP0A03"))
Name(_ADR, 0x00)
Name(_UID, 1)
}
}
#include "acpi-dsdt-pci-crs.dsl"
#include "acpi-dsdt-hpet.dsl"
/****************************************************************
* VGA
****************************************************************/
Scope(\_SB.PCI0) {
Device(VGA) {
Name(_ADR, 0x00020000)
OperationRegion(PCIC, PCI_Config, Zero, 0x4)
Field(PCIC, DWordAcc, NoLock, Preserve) {
VEND, 32
}
Method(_S1D, 0, NotSerialized) {
Return (0x00)
}
Method(_S2D, 0, NotSerialized) {
Return (0x00)
}
Method(_S3D, 0, NotSerialized) {
If (LEqual(VEND, 0x1001b36)) {
Return (0x03) // QXL
} Else {
Return (0x00)
}
}
}
}
/****************************************************************
* PIIX4 PM
****************************************************************/
Scope(\_SB.PCI0) {
Device(PX13) {
Name(_ADR, 0x00010003)
OperationRegion(P13C, PCI_Config, 0x00, 0xff)
}
}
/****************************************************************
* PIIX3 ISA bridge
****************************************************************/
Scope(\_SB.PCI0) {
Device(ISA) {
Name(_ADR, 0x00010000)
/* PIIX PCI to ISA irq remapping */
OperationRegion(P40C, PCI_Config, 0x60, 0x04)
/* enable bits */
Field(\_SB.PCI0.PX13.P13C, AnyAcc, NoLock, Preserve) {
Offset(0x5f),
, 7,
LPEN, 1, // LPT
Offset(0x67),
, 3,
CAEN, 1, // COM1
, 3,
CBEN, 1, // COM2
}
Name(FDEN, 1)
}
}
#include "acpi-dsdt-isa.dsl"
/****************************************************************
* PCI hotplug
****************************************************************/
Scope(\_SB.PCI0) {
OperationRegion(PCST, SystemIO, 0xae00, 0x08)
Field(PCST, DWordAcc, NoLock, WriteAsZeros) {
PCIU, 32,
PCID, 32,
}
OperationRegion(SEJ, SystemIO, 0xae08, 0x04)
Field(SEJ, DWordAcc, NoLock, WriteAsZeros) {
B0EJ, 32,
}
/* Methods called by bulk generated PCI devices below */
/* Methods called by hotplug devices */
Method(PCEJ, 1, NotSerialized) {
// _EJ0 method - eject callback
Store(ShiftLeft(1, Arg0), B0EJ)
Return (0x0)
}
/* Hotplug notification method supplied by SSDT */
External(\_SB.PCI0.PCNT, MethodObj)
/* PCI hotplug notify method */
Method(PCNF, 0) {
// Local0 = iterator
Store(Zero, Local0)
While (LLess(Local0, 31)) {
Increment(Local0)
If (And(PCIU, ShiftLeft(1, Local0))) {
PCNT(Local0, 1)
}
If (And(PCID, ShiftLeft(1, Local0))) {
PCNT(Local0, 3)
}
}
}
}
/****************************************************************
* PCI IRQs
****************************************************************/
Scope(\_SB) {
Scope(PCI0) {
Name(_PRT, Package() {
/* PCI IRQ routing table, example from ACPI 2.0a specification,
section 6.2.8.1 */
/* Note: we provide the same info as the PCI routing
table of the Bochs BIOS */
#define prt_slot(nr, lnk0, lnk1, lnk2, lnk3) \
Package() { nr##ffff, 0, lnk0, 0 }, \
Package() { nr##ffff, 1, lnk1, 0 }, \
Package() { nr##ffff, 2, lnk2, 0 }, \
Package() { nr##ffff, 3, lnk3, 0 }
#define prt_slot0(nr) prt_slot(nr, LNKD, LNKA, LNKB, LNKC)
#define prt_slot1(nr) prt_slot(nr, LNKA, LNKB, LNKC, LNKD)
#define prt_slot2(nr) prt_slot(nr, LNKB, LNKC, LNKD, LNKA)
#define prt_slot3(nr) prt_slot(nr, LNKC, LNKD, LNKA, LNKB)
prt_slot0(0x0000),
/* Device 1 is power mgmt device, and can only use irq 9 */
prt_slot(0x0001, LNKS, LNKB, LNKC, LNKD),
prt_slot2(0x0002),
prt_slot3(0x0003),
prt_slot0(0x0004),
prt_slot1(0x0005),
prt_slot2(0x0006),
prt_slot3(0x0007),
prt_slot0(0x0008),
prt_slot1(0x0009),
prt_slot2(0x000a),
prt_slot3(0x000b),
prt_slot0(0x000c),
prt_slot1(0x000d),
prt_slot2(0x000e),
prt_slot3(0x000f),
prt_slot0(0x0010),
prt_slot1(0x0011),
prt_slot2(0x0012),
prt_slot3(0x0013),
prt_slot0(0x0014),
prt_slot1(0x0015),
prt_slot2(0x0016),
prt_slot3(0x0017),
prt_slot0(0x0018),
prt_slot1(0x0019),
prt_slot2(0x001a),
prt_slot3(0x001b),
prt_slot0(0x001c),
prt_slot1(0x001d),
prt_slot2(0x001e),
prt_slot3(0x001f),
})
}
Field(PCI0.ISA.P40C, ByteAcc, NoLock, Preserve) {
PRQ0, 8,
PRQ1, 8,
PRQ2, 8,
PRQ3, 8
}
Method(IQST, 1, NotSerialized) {
// _STA method - get status
If (And(0x80, Arg0)) {
Return (0x09)
}
Return (0x0B)
}
Method(IQCR, 1, NotSerialized) {
// _CRS method - get current settings
Name(PRR0, ResourceTemplate() {
Interrupt(, Level, ActiveHigh, Shared) { 0 }
})
CreateDWordField(PRR0, 0x05, PRRI)
If (LLess(Arg0, 0x80)) {
Store(Arg0, PRRI)
}
Return (PRR0)
}
#define define_link(link, uid, reg) \
Device(link) { \
Name(_HID, EISAID("PNP0C0F")) \
Name(_UID, uid) \
Name(_PRS, ResourceTemplate() { \
Interrupt(, Level, ActiveHigh, Shared) { \
5, 10, 11 \
} \
}) \
Method(_STA, 0, NotSerialized) { \
Return (IQST(reg)) \
} \
Method(_DIS, 0, NotSerialized) { \
Or(reg, 0x80, reg) \
} \
Method(_CRS, 0, NotSerialized) { \
Return (IQCR(reg)) \
} \
Method(_SRS, 1, NotSerialized) { \
CreateDWordField(Arg0, 0x05, PRRI) \
Store(PRRI, reg) \
} \
}
define_link(LNKA, 0, PRQ0)
define_link(LNKB, 1, PRQ1)
define_link(LNKC, 2, PRQ2)
define_link(LNKD, 3, PRQ3)
Device(LNKS) {
Name(_HID, EISAID("PNP0C0F"))
Name(_UID, 4)
Name(_PRS, ResourceTemplate() {
Interrupt(, Level, ActiveHigh, Shared) { 9 }
})
// The SCI cannot be disabled and is always attached to GSI 9,
// so these are no-ops. We only need this link to override the
// polarity to active high and match the content of the MADT.
Method(_STA, 0, NotSerialized) { Return (0x0b) }
Method(_DIS, 0, NotSerialized) { }
Method(_CRS, 0, NotSerialized) { Return (_PRS) }
Method(_SRS, 1, NotSerialized) { }
}
}
#include "acpi-dsdt-cpu-hotplug.dsl"
/****************************************************************
* General purpose events
****************************************************************/
Scope(\_GPE) {
Name(_HID, "ACPI0006")
Method(_L00) {
}
Method(_E01) {
// PCI hotplug event
\_SB.PCI0.PCNF()
}
Method(_E02) {
// CPU hotplug event
\_SB.PRSC()
}
Method(_L03) {
}
Method(_L04) {
}
Method(_L05) {
}
Method(_L06) {
}
Method(_L07) {
}
Method(_L08) {
}
Method(_L09) {
}
Method(_L0A) {
}
Method(_L0B) {
}
Method(_L0C) {
}
Method(_L0D) {
}
Method(_L0E) {
}
Method(_L0F) {
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,158 @@
/* Dynamic linker/loader of ACPI tables
*
* Copyright (C) 2013 Red Hat Inc
*
* Author: Michael S. Tsirkin <mst@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "bios-linker-loader.h"
#include "hw/nvram/fw_cfg.h"
#include <string.h>
#include <assert.h>
#include "qemu/bswap.h"
#define BIOS_LINKER_LOADER_FILESZ FW_CFG_MAX_FILE_PATH
struct BiosLinkerLoaderEntry {
uint32_t command;
union {
/*
* COMMAND_ALLOCATE - allocate a table from @alloc.file
* subject to @alloc.align alignment (must be power of 2)
* and @alloc.zone (can be HIGH or FSEG) requirements.
*
* Must appear exactly once for each file, and before
* this file is referenced by any other command.
*/
struct {
char file[BIOS_LINKER_LOADER_FILESZ];
uint32_t align;
uint8_t zone;
} alloc;
/*
* COMMAND_ADD_POINTER - patch the table (originating from
* @dest_file) at @pointer.offset, by adding a pointer to the table
* originating from @src_file. 1,2,4 or 8 byte unsigned
* addition is used depending on @pointer.size.
*/
struct {
char dest_file[BIOS_LINKER_LOADER_FILESZ];
char src_file[BIOS_LINKER_LOADER_FILESZ];
uint32_t offset;
uint8_t size;
} pointer;
/*
* COMMAND_ADD_CHECKSUM - calculate checksum of the range specified by
* @cksum_start and @cksum_length fields,
* and then add the value at @cksum.offset.
* Checksum simply sums -X for each byte X in the range
* using 8-bit math.
*/
struct {
char file[BIOS_LINKER_LOADER_FILESZ];
uint32_t offset;
uint32_t start;
uint32_t length;
} cksum;
/* padding */
char pad[124];
};
} QEMU_PACKED;
typedef struct BiosLinkerLoaderEntry BiosLinkerLoaderEntry;
enum {
BIOS_LINKER_LOADER_COMMAND_ALLOCATE = 0x1,
BIOS_LINKER_LOADER_COMMAND_ADD_POINTER = 0x2,
BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM = 0x3,
};
enum {
BIOS_LINKER_LOADER_ALLOC_ZONE_HIGH = 0x1,
BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG = 0x2,
};
GArray *bios_linker_loader_init(void)
{
return g_array_new(false, true /* clear */, sizeof(BiosLinkerLoaderEntry));
}
/* Free linker wrapper and return the linker array. */
void *bios_linker_loader_cleanup(GArray *linker)
{
return g_array_free(linker, false);
}
void bios_linker_loader_alloc(GArray *linker,
const char *file,
uint32_t alloc_align,
bool alloc_fseg)
{
BiosLinkerLoaderEntry entry;
memset(&entry, 0, sizeof entry);
strncpy(entry.alloc.file, file, sizeof entry.alloc.file - 1);
entry.command = cpu_to_le32(BIOS_LINKER_LOADER_COMMAND_ALLOCATE);
entry.alloc.align = cpu_to_le32(alloc_align);
entry.alloc.zone = cpu_to_le32(alloc_fseg ?
BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG :
BIOS_LINKER_LOADER_ALLOC_ZONE_HIGH);
/* Alloc entries must come first, so prepend them */
g_array_prepend_val(linker, entry);
}
void bios_linker_loader_add_checksum(GArray *linker, const char *file,
void *table,
void *start, unsigned size,
uint8_t *checksum)
{
BiosLinkerLoaderEntry entry;
memset(&entry, 0, sizeof entry);
strncpy(entry.cksum.file, file, sizeof entry.cksum.file - 1);
entry.command = cpu_to_le32(BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM);
entry.cksum.offset = cpu_to_le32(checksum - (uint8_t *)table);
entry.cksum.start = cpu_to_le32((uint8_t *)start - (uint8_t *)table);
entry.cksum.length = cpu_to_le32(size);
g_array_append_val(linker, entry);
}
void bios_linker_loader_add_pointer(GArray *linker,
const char *dest_file,
const char *src_file,
GArray *table, void *pointer,
uint8_t pointer_size)
{
BiosLinkerLoaderEntry entry;
memset(&entry, 0, sizeof entry);
strncpy(entry.pointer.dest_file, dest_file,
sizeof entry.pointer.dest_file - 1);
strncpy(entry.pointer.src_file, src_file,
sizeof entry.pointer.src_file - 1);
entry.command = cpu_to_le32(BIOS_LINKER_LOADER_COMMAND_ADD_POINTER);
entry.pointer.offset = cpu_to_le32((gchar *)pointer - table->data);
entry.pointer.size = pointer_size;
assert(pointer_size == 1 || pointer_size == 2 ||
pointer_size == 4 || pointer_size == 8);
g_array_append_val(linker, entry);
}

View File

@ -0,0 +1,27 @@
#ifndef BIOS_LINKER_LOADER_H
#define BIOS_LINKER_LOADER_H
#include <glib.h>
#include <stdbool.h>
#include <inttypes.h>
GArray *bios_linker_loader_init(void);
void bios_linker_loader_alloc(GArray *linker,
const char *file,
uint32_t alloc_align,
bool alloc_fseg);
void bios_linker_loader_add_checksum(GArray *linker, const char *file,
void *table,
void *start, unsigned size,
uint8_t *checksum);
void bios_linker_loader_add_pointer(GArray *linker,
const char *dest_file,
const char *src_file,
GArray *table, void *pointer,
uint8_t pointer_size);
void *bios_linker_loader_cleanup(GArray *linker);
#endif

View File

@ -56,6 +56,7 @@
#include "hw/cpu/icc_bus.h"
#include "hw/boards.h"
#include "hw/pci/pci_host.h"
#include "acpi-build.h"
/* debug PC/ISA interrupts */
//#define DEBUG_IRQ
@ -1040,6 +1041,7 @@ void pc_guest_info_machine_done(Notifier *notifier, void *data)
PcGuestInfoState,
machine_done);
pc_fw_cfg_guest_info(&guest_info_state->info);
acpi_setup(&guest_info_state->info);
}
PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size,
@ -1047,6 +1049,27 @@ PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size,
{
PcGuestInfoState *guest_info_state = g_malloc0(sizeof *guest_info_state);
PcGuestInfo *guest_info = &guest_info_state->info;
int i, j;
guest_info->ram_size = below_4g_mem_size + above_4g_mem_size;
guest_info->apic_id_limit = pc_apic_id_limit(max_cpus);
guest_info->apic_xrupt_override = kvm_allows_irq0_override();
guest_info->numa_nodes = nb_numa_nodes;
guest_info->node_mem = g_memdup(node_mem, guest_info->numa_nodes *
sizeof *guest_info->node_mem);
guest_info->node_cpu = g_malloc0(guest_info->apic_id_limit *
sizeof *guest_info->node_cpu);
for (i = 0; i < max_cpus; i++) {
unsigned int apic_id = x86_cpu_apic_id_from_index(i);
assert(apic_id < guest_info->apic_id_limit);
for (j = 0; j < nb_numa_nodes; j++) {
if (test_bit(i, node_cpumask[j])) {
guest_info->node_cpu[apic_id] = j;
break;
}
}
}
guest_info_state->machine_done.notify = pc_guest_info_machine_done;
qemu_add_machine_init_done_notifier(&guest_info_state->machine_done);
@ -1093,7 +1116,7 @@ void pc_acpi_init(const char *default_dsdt)
opts = qemu_opts_parse(qemu_find_opts("acpi"), arg, 0);
g_assert(opts != NULL);
acpi_table_add(opts, &err);
acpi_table_add_builtin(opts, &err);
if (err) {
error_report("WARNING: failed to load %s: %s", filename,
error_get_pretty(err));

View File

@ -59,6 +59,7 @@ static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
static bool has_pvpanic;
static bool has_pci_info = true;
static bool has_acpi_build = true;
/* PC hardware initialisation */
static void pc_init1(QEMUMachineInitArgs *args,
@ -122,6 +123,9 @@ static void pc_init1(QEMUMachineInitArgs *args,
}
guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size);
guest_info->has_acpi_build = has_acpi_build;
guest_info->has_pci_info = has_pci_info;
guest_info->isapc_ram_fw = !pci_enabled;
@ -240,6 +244,7 @@ static void pc_compat_1_6(QEMUMachineInitArgs *args)
{
has_pci_info = false;
rom_file_in_ram = false;
has_acpi_build = false;
}
static void pc_compat_1_5(QEMUMachineInitArgs *args)

View File

@ -49,6 +49,7 @@
static bool has_pvpanic;
static bool has_pci_info = true;
static bool has_acpi_build = true;
/* PC hardware initialisation */
static void pc_q35_init(QEMUMachineInitArgs *args)
@ -111,6 +112,7 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size);
guest_info->has_pci_info = has_pci_info;
guest_info->isapc_ram_fw = false;
guest_info->has_acpi_build = has_acpi_build;
/* allocate ram and load rom/bios */
if (!xen_enabled()) {
@ -224,6 +226,7 @@ static void pc_compat_1_6(QEMUMachineInitArgs *args)
{
has_pci_info = false;
rom_file_in_ram = false;
has_acpi_build = false;
}
static void pc_compat_1_5(QEMUMachineInitArgs *args)

452
hw/i386/q35-acpi-dsdt.dsl Normal file
View File

@ -0,0 +1,452 @@
/*
* Bochs/QEMU ACPI DSDT ASL definition
*
* Copyright (c) 2006 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* Copyright (c) 2010 Isaku Yamahata
* yamahata at valinux co jp
* Based on acpi-dsdt.dsl, but heavily modified for q35 chipset.
*/
ACPI_EXTRACT_ALL_CODE Q35AcpiDsdtAmlCode
DefinitionBlock (
"q35-acpi-dsdt.aml",// Output Filename
"DSDT", // Signature
0x01, // DSDT Compliance Revision
"BXPC", // OEMID
"BXDSDT", // TABLE ID
0x2 // OEM Revision
)
{
#include "acpi-dsdt-dbug.dsl"
Scope(\_SB) {
OperationRegion(PCST, SystemIO, 0xae00, 0x0c)
OperationRegion(PCSB, SystemIO, 0xae0c, 0x01)
Field(PCSB, AnyAcc, NoLock, WriteAsZeros) {
PCIB, 8,
}
}
/****************************************************************
* PCI Bus definition
****************************************************************/
Scope(\_SB) {
Device(PCI0) {
Name(_HID, EisaId("PNP0A08"))
Name(_CID, EisaId("PNP0A03"))
Name(_ADR, 0x00)
Name(_UID, 1)
// _OSC: based on sample of ACPI3.0b spec
Name(SUPP, 0) // PCI _OSC Support Field value
Name(CTRL, 0) // PCI _OSC Control Field value
Method(_OSC, 4) {
// Create DWORD-addressable fields from the Capabilities Buffer
CreateDWordField(Arg3, 0, CDW1)
// Check for proper UUID
If (LEqual(Arg0, ToUUID("33DB4D5B-1FF7-401C-9657-7441C03DD766"))) {
// Create DWORD-addressable fields from the Capabilities Buffer
CreateDWordField(Arg3, 4, CDW2)
CreateDWordField(Arg3, 8, CDW3)
// Save Capabilities DWORD2 & 3
Store(CDW2, SUPP)
Store(CDW3, CTRL)
// Always allow native PME, AER (no dependencies)
// Never allow SHPC (no SHPC controller in this system)
And(CTRL, 0x1D, CTRL)
#if 0 // For now, nothing to do
If (Not(And(CDW1, 1))) { // Query flag clear?
// Disable GPEs for features granted native control.
If (And(CTRL, 0x01)) { // Hot plug control granted?
Store(0, HPCE) // clear the hot plug SCI enable bit
Store(1, HPCS) // clear the hot plug SCI status bit
}
If (And(CTRL, 0x04)) { // PME control granted?
Store(0, PMCE) // clear the PME SCI enable bit
Store(1, PMCS) // clear the PME SCI status bit
}
If (And(CTRL, 0x10)) { // OS restoring PCI Express cap structure?
// Set status to not restore PCI Express cap structure
// upon resume from S3
Store(1, S3CR)
}
}
#endif
If (LNotEqual(Arg1, One)) {
// Unknown revision
Or(CDW1, 0x08, CDW1)
}
If (LNotEqual(CDW3, CTRL)) {
// Capabilities bits were masked
Or(CDW1, 0x10, CDW1)
}
// Update DWORD3 in the buffer
Store(CTRL, CDW3)
} Else {
Or(CDW1, 4, CDW1) // Unrecognized UUID
}
Return (Arg3)
}
}
}
#include "acpi-dsdt-pci-crs.dsl"
#include "acpi-dsdt-hpet.dsl"
/****************************************************************
* VGA
****************************************************************/
Scope(\_SB.PCI0) {
Device(VGA) {
Name(_ADR, 0x00010000)
Method(_S1D, 0, NotSerialized) {
Return (0x00)
}
Method(_S2D, 0, NotSerialized) {
Return (0x00)
}
Method(_S3D, 0, NotSerialized) {
Return (0x00)
}
}
}
/****************************************************************
* LPC ISA bridge
****************************************************************/
Scope(\_SB.PCI0) {
/* PCI D31:f0 LPC ISA bridge */
Device(ISA) {
/* PCI D31:f0 */
Name(_ADR, 0x001f0000)
/* ICH9 PCI to ISA irq remapping */
OperationRegion(PIRQ, PCI_Config, 0x60, 0x0C)
OperationRegion(LPCD, PCI_Config, 0x80, 0x2)
Field(LPCD, AnyAcc, NoLock, Preserve) {
COMA, 3,
, 1,
COMB, 3,
Offset(0x01),
LPTD, 2,
, 2,
FDCD, 2
}
OperationRegion(LPCE, PCI_Config, 0x82, 0x2)
Field(LPCE, AnyAcc, NoLock, Preserve) {
CAEN, 1,
CBEN, 1,
LPEN, 1,
FDEN, 1
}
}
}
#include "acpi-dsdt-isa.dsl"
/****************************************************************
* PCI IRQs
****************************************************************/
/* Zero => PIC mode, One => APIC Mode */
Name(\PICF, Zero)
Method(\_PIC, 1, NotSerialized) {
Store(Arg0, \PICF)
}
Scope(\_SB) {
Scope(PCI0) {
#define prt_slot_lnk(nr, lnk0, lnk1, lnk2, lnk3) \
Package() { nr##ffff, 0, lnk0, 0 }, \
Package() { nr##ffff, 1, lnk1, 0 }, \
Package() { nr##ffff, 2, lnk2, 0 }, \
Package() { nr##ffff, 3, lnk3, 0 }
#define prt_slot_lnkA(nr) prt_slot_lnk(nr, LNKA, LNKB, LNKC, LNKD)
#define prt_slot_lnkB(nr) prt_slot_lnk(nr, LNKB, LNKC, LNKD, LNKA)
#define prt_slot_lnkC(nr) prt_slot_lnk(nr, LNKC, LNKD, LNKA, LNKB)
#define prt_slot_lnkD(nr) prt_slot_lnk(nr, LNKD, LNKA, LNKB, LNKC)
#define prt_slot_lnkE(nr) prt_slot_lnk(nr, LNKE, LNKF, LNKG, LNKH)
#define prt_slot_lnkF(nr) prt_slot_lnk(nr, LNKF, LNKG, LNKH, LNKE)
#define prt_slot_lnkG(nr) prt_slot_lnk(nr, LNKG, LNKH, LNKE, LNKF)
#define prt_slot_lnkH(nr) prt_slot_lnk(nr, LNKH, LNKE, LNKF, LNKG)
Name(PRTP, package() {
prt_slot_lnkE(0x0000),
prt_slot_lnkF(0x0001),
prt_slot_lnkG(0x0002),
prt_slot_lnkH(0x0003),
prt_slot_lnkE(0x0004),
prt_slot_lnkF(0x0005),
prt_slot_lnkG(0x0006),
prt_slot_lnkH(0x0007),
prt_slot_lnkE(0x0008),
prt_slot_lnkF(0x0009),
prt_slot_lnkG(0x000a),
prt_slot_lnkH(0x000b),
prt_slot_lnkE(0x000c),
prt_slot_lnkF(0x000d),
prt_slot_lnkG(0x000e),
prt_slot_lnkH(0x000f),
prt_slot_lnkE(0x0010),
prt_slot_lnkF(0x0011),
prt_slot_lnkG(0x0012),
prt_slot_lnkH(0x0013),
prt_slot_lnkE(0x0014),
prt_slot_lnkF(0x0015),
prt_slot_lnkG(0x0016),
prt_slot_lnkH(0x0017),
prt_slot_lnkE(0x0018),
/* INTA -> PIRQA for slot 25 - 31
see the default value of D<N>IR */
prt_slot_lnkA(0x0019),
prt_slot_lnkA(0x001a),
prt_slot_lnkA(0x001b),
prt_slot_lnkA(0x001c),
prt_slot_lnkA(0x001d),
/* PCIe->PCI bridge. use PIRQ[E-H] */
prt_slot_lnkE(0x001e),
prt_slot_lnkA(0x001f)
})
#define prt_slot_gsi(nr, gsi0, gsi1, gsi2, gsi3) \
Package() { nr##ffff, 0, gsi0, 0 }, \
Package() { nr##ffff, 1, gsi1, 0 }, \
Package() { nr##ffff, 2, gsi2, 0 }, \
Package() { nr##ffff, 3, gsi3, 0 }
#define prt_slot_gsiA(nr) prt_slot_gsi(nr, GSIA, GSIB, GSIC, GSID)
#define prt_slot_gsiB(nr) prt_slot_gsi(nr, GSIB, GSIC, GSID, GSIA)
#define prt_slot_gsiC(nr) prt_slot_gsi(nr, GSIC, GSID, GSIA, GSIB)
#define prt_slot_gsiD(nr) prt_slot_gsi(nr, GSID, GSIA, GSIB, GSIC)
#define prt_slot_gsiE(nr) prt_slot_gsi(nr, GSIE, GSIF, GSIG, GSIH)
#define prt_slot_gsiF(nr) prt_slot_gsi(nr, GSIF, GSIG, GSIH, GSIE)
#define prt_slot_gsiG(nr) prt_slot_gsi(nr, GSIG, GSIH, GSIE, GSIF)
#define prt_slot_gsiH(nr) prt_slot_gsi(nr, GSIH, GSIE, GSIF, GSIG)
Name(PRTA, package() {
prt_slot_gsiE(0x0000),
prt_slot_gsiF(0x0001),
prt_slot_gsiG(0x0002),
prt_slot_gsiH(0x0003),
prt_slot_gsiE(0x0004),
prt_slot_gsiF(0x0005),
prt_slot_gsiG(0x0006),
prt_slot_gsiH(0x0007),
prt_slot_gsiE(0x0008),
prt_slot_gsiF(0x0009),
prt_slot_gsiG(0x000a),
prt_slot_gsiH(0x000b),
prt_slot_gsiE(0x000c),
prt_slot_gsiF(0x000d),
prt_slot_gsiG(0x000e),
prt_slot_gsiH(0x000f),
prt_slot_gsiE(0x0010),
prt_slot_gsiF(0x0011),
prt_slot_gsiG(0x0012),
prt_slot_gsiH(0x0013),
prt_slot_gsiE(0x0014),
prt_slot_gsiF(0x0015),
prt_slot_gsiG(0x0016),
prt_slot_gsiH(0x0017),
prt_slot_gsiE(0x0018),
/* INTA -> PIRQA for slot 25 - 31, but 30
see the default value of D<N>IR */
prt_slot_gsiA(0x0019),
prt_slot_gsiA(0x001a),
prt_slot_gsiA(0x001b),
prt_slot_gsiA(0x001c),
prt_slot_gsiA(0x001d),
/* PCIe->PCI bridge. use PIRQ[E-H] */
prt_slot_gsiE(0x001e),
prt_slot_gsiA(0x001f)
})
Method(_PRT, 0, NotSerialized) {
/* PCI IRQ routing table, example from ACPI 2.0a specification,
section 6.2.8.1 */
/* Note: we provide the same info as the PCI routing
table of the Bochs BIOS */
If (LEqual(\PICF, Zero)) {
Return (PRTP)
} Else {
Return (PRTA)
}
}
}
Field(PCI0.ISA.PIRQ, ByteAcc, NoLock, Preserve) {
PRQA, 8,
PRQB, 8,
PRQC, 8,
PRQD, 8,
Offset(0x08),
PRQE, 8,
PRQF, 8,
PRQG, 8,
PRQH, 8
}
Method(IQST, 1, NotSerialized) {
// _STA method - get status
If (And(0x80, Arg0)) {
Return (0x09)
}
Return (0x0B)
}
Method(IQCR, 1, NotSerialized) {
// _CRS method - get current settings
Name(PRR0, ResourceTemplate() {
Interrupt(, Level, ActiveHigh, Shared) { 0 }
})
CreateDWordField(PRR0, 0x05, PRRI)
Store(And(Arg0, 0x0F), PRRI)
Return (PRR0)
}
#define define_link(link, uid, reg) \
Device(link) { \
Name(_HID, EISAID("PNP0C0F")) \
Name(_UID, uid) \
Name(_PRS, ResourceTemplate() { \
Interrupt(, Level, ActiveHigh, Shared) { \
5, 10, 11 \
} \
}) \
Method(_STA, 0, NotSerialized) { \
Return (IQST(reg)) \
} \
Method(_DIS, 0, NotSerialized) { \
Or(reg, 0x80, reg) \
} \
Method(_CRS, 0, NotSerialized) { \
Return (IQCR(reg)) \
} \
Method(_SRS, 1, NotSerialized) { \
CreateDWordField(Arg0, 0x05, PRRI) \
Store(PRRI, reg) \
} \
}
define_link(LNKA, 0, PRQA)
define_link(LNKB, 1, PRQB)
define_link(LNKC, 2, PRQC)
define_link(LNKD, 3, PRQD)
define_link(LNKE, 4, PRQE)
define_link(LNKF, 5, PRQF)
define_link(LNKG, 6, PRQG)
define_link(LNKH, 7, PRQH)
#define define_gsi_link(link, uid, gsi) \
Device(link) { \
Name(_HID, EISAID("PNP0C0F")) \
Name(_UID, uid) \
Name(_PRS, ResourceTemplate() { \
Interrupt(, Level, ActiveHigh, Shared) { \
gsi \
} \
}) \
Name(_CRS, ResourceTemplate() { \
Interrupt(, Level, ActiveHigh, Shared) { \
gsi \
} \
}) \
Method(_SRS, 1, NotSerialized) { \
} \
}
define_gsi_link(GSIA, 0, 0x10)
define_gsi_link(GSIB, 0, 0x11)
define_gsi_link(GSIC, 0, 0x12)
define_gsi_link(GSID, 0, 0x13)
define_gsi_link(GSIE, 0, 0x14)
define_gsi_link(GSIF, 0, 0x15)
define_gsi_link(GSIG, 0, 0x16)
define_gsi_link(GSIH, 0, 0x17)
}
#include "acpi-dsdt-cpu-hotplug.dsl"
/****************************************************************
* General purpose events
****************************************************************/
Scope(\_GPE) {
Name(_HID, "ACPI0006")
Method(_L00) {
}
Method(_L01) {
// CPU hotplug event
\_SB.PRSC()
}
Method(_L02) {
}
Method(_L03) {
}
Method(_L04) {
}
Method(_L05) {
}
Method(_L06) {
}
Method(_L07) {
}
Method(_L08) {
}
Method(_L09) {
}
Method(_L0A) {
}
Method(_L0B) {
}
Method(_L0C) {
}
Method(_L0D) {
}
Method(_L0E) {
}
Method(_L0F) {
}
}
}

File diff suppressed because it is too large Load Diff

119
hw/i386/ssdt-misc.dsl Normal file
View File

@ -0,0 +1,119 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
ACPI_EXTRACT_ALL_CODE ssdp_misc_aml
DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1)
{
/****************************************************************
* PCI memory ranges
****************************************************************/
Scope(\) {
ACPI_EXTRACT_NAME_DWORD_CONST acpi_pci32_start
Name(P0S, 0x12345678)
ACPI_EXTRACT_NAME_DWORD_CONST acpi_pci32_end
Name(P0E, 0x12345678)
ACPI_EXTRACT_NAME_BYTE_CONST acpi_pci64_valid
Name(P1V, 0x12)
ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_start
Name(P1S, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 })
ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_end
Name(P1E, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 })
ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_length
Name(P1L, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 })
}
/****************************************************************
* Suspend
****************************************************************/
Scope(\) {
/*
* S3 (suspend-to-ram), S4 (suspend-to-disk) and S5 (power-off) type codes:
* must match piix4 emulation.
*/
ACPI_EXTRACT_NAME_STRING acpi_s3_name
Name(_S3, Package(0x04) {
One, /* PM1a_CNT.SLP_TYP */
One, /* PM1b_CNT.SLP_TYP */
Zero, /* reserved */
Zero /* reserved */
})
ACPI_EXTRACT_NAME_STRING acpi_s4_name
ACPI_EXTRACT_PKG_START acpi_s4_pkg
Name(_S4, Package(0x04) {
0x2, /* PM1a_CNT.SLP_TYP */
0x2, /* PM1b_CNT.SLP_TYP */
Zero, /* reserved */
Zero /* reserved */
})
Name(_S5, Package(0x04) {
Zero, /* PM1a_CNT.SLP_TYP */
Zero, /* PM1b_CNT.SLP_TYP */
Zero, /* reserved */
Zero /* reserved */
})
}
External(\_SB.PCI0, DeviceObj)
External(\_SB.PCI0.ISA, DeviceObj)
Scope(\_SB.PCI0.ISA) {
Device(PEVT) {
Name(_HID, "QEMU0001")
/* PEST will be patched to be Zero if no such device */
ACPI_EXTRACT_NAME_WORD_CONST ssdt_isa_pest
Name(PEST, 0xFFFF)
OperationRegion(PEOR, SystemIO, PEST, 0x01)
Field(PEOR, ByteAcc, NoLock, Preserve) {
PEPT, 8,
}
Method(_STA, 0, NotSerialized) {
Store(PEST, Local0)
If (LEqual(Local0, Zero)) {
Return (0x00)
} Else {
Return (0x0F)
}
}
Method(RDPT, 0, NotSerialized) {
Store(PEPT, Local0)
Return (Local0)
}
Method(WRPT, 1, NotSerialized) {
Store(Arg0, PEPT)
}
Name(_CRS, ResourceTemplate() {
IO(Decode16, 0x00, 0x00, 0x01, 0x01, IO)
})
CreateWordField(_CRS, IO._MIN, IOMN)
CreateWordField(_CRS, IO._MAX, IOMX)
Method(_INI, 0, NotSerialized) {
Store(PEST, IOMN)
Store(PEST, IOMX)
}
}
}
}

View File

@ -0,0 +1,386 @@
static unsigned char acpi_pci64_length[] = {
0x6f
};
static unsigned char acpi_s4_pkg[] = {
0x8f
};
static unsigned char acpi_s3_name[] = {
0x7c
};
static unsigned char acpi_pci32_start[] = {
0x2f
};
static unsigned char acpi_pci64_valid[] = {
0x43
};
static unsigned char ssdp_misc_aml[] = {
0x53,
0x53,
0x44,
0x54,
0x62,
0x1,
0x0,
0x0,
0x1,
0x76,
0x42,
0x58,
0x50,
0x43,
0x0,
0x0,
0x42,
0x58,
0x53,
0x53,
0x44,
0x54,
0x53,
0x55,
0x1,
0x0,
0x0,
0x0,
0x49,
0x4e,
0x54,
0x4c,
0x23,
0x8,
0x13,
0x20,
0x10,
0x42,
0x5,
0x5c,
0x0,
0x8,
0x50,
0x30,
0x53,
0x5f,
0xc,
0x78,
0x56,
0x34,
0x12,
0x8,
0x50,
0x30,
0x45,
0x5f,
0xc,
0x78,
0x56,
0x34,
0x12,
0x8,
0x50,
0x31,
0x56,
0x5f,
0xa,
0x12,
0x8,
0x50,
0x31,
0x53,
0x5f,
0x11,
0xb,
0xa,
0x8,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x8,
0x50,
0x31,
0x45,
0x5f,
0x11,
0xb,
0xa,
0x8,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x8,
0x50,
0x31,
0x4c,
0x5f,
0x11,
0xb,
0xa,
0x8,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x10,
0x29,
0x5c,
0x0,
0x8,
0x5f,
0x53,
0x33,
0x5f,
0x12,
0x6,
0x4,
0x1,
0x1,
0x0,
0x0,
0x8,
0x5f,
0x53,
0x34,
0x5f,
0x12,
0x8,
0x4,
0xa,
0x2,
0xa,
0x2,
0x0,
0x0,
0x8,
0x5f,
0x53,
0x35,
0x5f,
0x12,
0x6,
0x4,
0x0,
0x0,
0x0,
0x0,
0x10,
0x40,
0xc,
0x5c,
0x2f,
0x3,
0x5f,
0x53,
0x42,
0x5f,
0x50,
0x43,
0x49,
0x30,
0x49,
0x53,
0x41,
0x5f,
0x5b,
0x82,
0x4d,
0xa,
0x50,
0x45,
0x56,
0x54,
0x8,
0x5f,
0x48,
0x49,
0x44,
0xd,
0x51,
0x45,
0x4d,
0x55,
0x30,
0x30,
0x30,
0x31,
0x0,
0x8,
0x50,
0x45,
0x53,
0x54,
0xb,
0xff,
0xff,
0x5b,
0x80,
0x50,
0x45,
0x4f,
0x52,
0x1,
0x50,
0x45,
0x53,
0x54,
0x1,
0x5b,
0x81,
0xb,
0x50,
0x45,
0x4f,
0x52,
0x1,
0x50,
0x45,
0x50,
0x54,
0x8,
0x14,
0x18,
0x5f,
0x53,
0x54,
0x41,
0x0,
0x70,
0x50,
0x45,
0x53,
0x54,
0x60,
0xa0,
0x6,
0x93,
0x60,
0x0,
0xa4,
0x0,
0xa1,
0x4,
0xa4,
0xa,
0xf,
0x14,
0xe,
0x52,
0x44,
0x50,
0x54,
0x0,
0x70,
0x50,
0x45,
0x50,
0x54,
0x60,
0xa4,
0x60,
0x14,
0xc,
0x57,
0x52,
0x50,
0x54,
0x1,
0x70,
0x68,
0x50,
0x45,
0x50,
0x54,
0x8,
0x5f,
0x43,
0x52,
0x53,
0x11,
0xd,
0xa,
0xa,
0x47,
0x1,
0x0,
0x0,
0x0,
0x0,
0x1,
0x1,
0x79,
0x0,
0x8b,
0x5f,
0x43,
0x52,
0x53,
0xa,
0x2,
0x49,
0x4f,
0x4d,
0x4e,
0x8b,
0x5f,
0x43,
0x52,
0x53,
0xa,
0x4,
0x49,
0x4f,
0x4d,
0x58,
0x14,
0x18,
0x5f,
0x49,
0x4e,
0x49,
0x0,
0x70,
0x50,
0x45,
0x53,
0x54,
0x49,
0x4f,
0x4d,
0x4e,
0x70,
0x50,
0x45,
0x53,
0x54,
0x49,
0x4f,
0x4d,
0x58
};
static unsigned char ssdt_isa_pest[] = {
0xd0
};
static unsigned char acpi_s4_name[] = {
0x88
};
static unsigned char acpi_pci64_start[] = {
0x4d
};
static unsigned char acpi_pci64_end[] = {
0x5e
};
static unsigned char acpi_pci32_end[] = {
0x39
};

51
hw/i386/ssdt-pcihp.dsl Normal file
View File

@ -0,0 +1,51 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
ACPI_EXTRACT_ALL_CODE ssdp_pcihp_aml
DefinitionBlock ("ssdt-pcihp.aml", "SSDT", 0x01, "BXPC", "BXSSDTPCIHP", 0x1)
{
/****************************************************************
* PCI hotplug
****************************************************************/
/* Objects supplied by DSDT */
External(\_SB.PCI0, DeviceObj)
External(\_SB.PCI0.PCEJ, MethodObj)
Scope(\_SB.PCI0) {
/* Bulk generated PCI hotplug devices */
ACPI_EXTRACT_DEVICE_START ssdt_pcihp_start
ACPI_EXTRACT_DEVICE_END ssdt_pcihp_end
ACPI_EXTRACT_DEVICE_STRING ssdt_pcihp_name
// Method _EJ0 can be patched by BIOS to EJ0_
// at runtime, if the slot is detected to not support hotplug.
// Extract the offset of the address dword and the
// _EJ0 name to allow this patching.
Device(SAA) {
ACPI_EXTRACT_NAME_BYTE_CONST ssdt_pcihp_id
Name(_SUN, 0xAA)
ACPI_EXTRACT_NAME_DWORD_CONST ssdt_pcihp_adr
Name(_ADR, 0xAA0000)
ACPI_EXTRACT_METHOD_STRING ssdt_pcihp_ej0
Method(_EJ0, 1) {
Return (PCEJ(_SUN))
}
}
}
}

View File

@ -0,0 +1,108 @@
static unsigned char ssdt_pcihp_name[] = {
0x33
};
static unsigned char ssdt_pcihp_adr[] = {
0x44
};
static unsigned char ssdt_pcihp_end[] = {
0x58
};
static unsigned char ssdp_pcihp_aml[] = {
0x53,
0x53,
0x44,
0x54,
0x58,
0x0,
0x0,
0x0,
0x1,
0x76,
0x42,
0x58,
0x50,
0x43,
0x0,
0x0,
0x42,
0x58,
0x53,
0x53,
0x44,
0x54,
0x50,
0x43,
0x1,
0x0,
0x0,
0x0,
0x49,
0x4e,
0x54,
0x4c,
0x23,
0x8,
0x13,
0x20,
0x10,
0x33,
0x5c,
0x2e,
0x5f,
0x53,
0x42,
0x5f,
0x50,
0x43,
0x49,
0x30,
0x5b,
0x82,
0x26,
0x53,
0x41,
0x41,
0x5f,
0x8,
0x5f,
0x53,
0x55,
0x4e,
0xa,
0xaa,
0x8,
0x5f,
0x41,
0x44,
0x52,
0xc,
0x0,
0x0,
0xaa,
0x0,
0x14,
0xf,
0x5f,
0x45,
0x4a,
0x30,
0x1,
0xa4,
0x50,
0x43,
0x45,
0x4a,
0x5f,
0x53,
0x55,
0x4e
};
static unsigned char ssdt_pcihp_start[] = {
0x30
};
static unsigned char ssdt_pcihp_id[] = {
0x3d
};
static unsigned char ssdt_pcihp_ej0[] = {
0x4a
};

63
hw/i386/ssdt-proc.dsl Normal file
View File

@ -0,0 +1,63 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/* This file is the basis for the ssdt table generated in src/acpi.c.
* It defines the contents of the per-cpu Processor() object. At
* runtime, a dynamically generated SSDT will contain one copy of this
* AML snippet for every possible cpu in the system. The objects will
* be placed in the \_SB_ namespace.
*
* In addition to the aml code generated from this file, the
* src/acpi.c file creates a NTFY method with an entry for each cpu:
* Method(NTFY, 2) {
* If (LEqual(Arg0, 0x00)) { Notify(CP00, Arg1) }
* If (LEqual(Arg0, 0x01)) { Notify(CP01, Arg1) }
* ...
* }
* and a CPON array with the list of active and inactive cpus:
* Name(CPON, Package() { One, One, ..., Zero, Zero, ... })
*/
ACPI_EXTRACT_ALL_CODE ssdp_proc_aml
DefinitionBlock ("ssdt-proc.aml", "SSDT", 0x01, "BXPC", "BXSSDT", 0x1)
{
ACPI_EXTRACT_PROCESSOR_START ssdt_proc_start
ACPI_EXTRACT_PROCESSOR_END ssdt_proc_end
ACPI_EXTRACT_PROCESSOR_STRING ssdt_proc_name
Processor(CPAA, 0xAA, 0x00000000, 0x0) {
ACPI_EXTRACT_NAME_BYTE_CONST ssdt_proc_id
Name(ID, 0xAA)
/*
* The src/acpi.c code requires the above ACP_EXTRACT tags so that it can update
* CPAA and 0xAA with the appropriate CPU id (see
* SD_OFFSET_CPUHEX/CPUID1/CPUID2). Don't change the above without
* also updating the C code.
*/
Name(_HID, "ACPI0007")
External(CPMA, MethodObj)
External(CPST, MethodObj)
External(CPEJ, MethodObj)
Method(_MAT, 0) {
Return (CPMA(ID))
}
Method(_STA, 0) {
Return (CPST(ID))
}
Method(_EJ0, 1, NotSerialized) {
CPEJ(ID, Arg0)
}
}
}

View File

@ -0,0 +1,134 @@
static unsigned char ssdt_proc_name[] = {
0x28
};
static unsigned char ssdp_proc_aml[] = {
0x53,
0x53,
0x44,
0x54,
0x78,
0x0,
0x0,
0x0,
0x1,
0xb8,
0x42,
0x58,
0x50,
0x43,
0x0,
0x0,
0x42,
0x58,
0x53,
0x53,
0x44,
0x54,
0x0,
0x0,
0x1,
0x0,
0x0,
0x0,
0x49,
0x4e,
0x54,
0x4c,
0x23,
0x8,
0x13,
0x20,
0x5b,
0x83,
0x42,
0x5,
0x43,
0x50,
0x41,
0x41,
0xaa,
0x10,
0xb0,
0x0,
0x0,
0x0,
0x8,
0x49,
0x44,
0x5f,
0x5f,
0xa,
0xaa,
0x8,
0x5f,
0x48,
0x49,
0x44,
0xd,
0x41,
0x43,
0x50,
0x49,
0x30,
0x30,
0x30,
0x37,
0x0,
0x14,
0xf,
0x5f,
0x4d,
0x41,
0x54,
0x0,
0xa4,
0x43,
0x50,
0x4d,
0x41,
0x49,
0x44,
0x5f,
0x5f,
0x14,
0xf,
0x5f,
0x53,
0x54,
0x41,
0x0,
0xa4,
0x43,
0x50,
0x53,
0x54,
0x49,
0x44,
0x5f,
0x5f,
0x14,
0xf,
0x5f,
0x45,
0x4a,
0x30,
0x1,
0x43,
0x50,
0x45,
0x4a,
0x49,
0x44,
0x5f,
0x5f,
0x68
};
static unsigned char ssdt_proc_id[] = {
0x38
};
static unsigned char ssdt_proc_end[] = {
0x78
};
static unsigned char ssdt_proc_start[] = {
0x24
};

View File

@ -230,7 +230,7 @@ static void cmd646_update_irq(PCIIDEState *d)
!(pd->config[MRDMODE] & MRDMODE_BLK_CH0)) ||
((pd->config[MRDMODE] & MRDMODE_INTR_CH1) &&
!(pd->config[MRDMODE] & MRDMODE_BLK_CH1));
qemu_set_irq(pd->irq[0], pci_level);
pci_set_irq(pd, pci_level);
}
/* the PCI irq level is the logical OR of the two channels */

View File

@ -116,7 +116,7 @@ static int pci_ich9_ahci_init(PCIDevice *dev)
dev->config[0x90] = 1 << 6; /* Address Map Register - AHCI mode */
msi_init(dev, 0x50, 1, true, false);
d->ahci.irq = dev->irq[0];
d->ahci.irq = pci_allocate_irq(dev);
pci_register_bar(dev, ICH9_IDP_BAR, PCI_BASE_ADDRESS_SPACE_IO,
&d->ahci.idp);
@ -145,6 +145,7 @@ static void pci_ich9_uninit(PCIDevice *dev)
msi_uninit(dev);
ahci_uninit(&d->ahci);
qemu_free_irq(d->ahci.irq);
}
static void ich_ahci_class_init(ObjectClass *klass, void *data)

View File

@ -29,6 +29,7 @@
*/
#include "qemu-common.h"
#include "hw/hw.h"
#include "qapi/visitor.h"
#include "qemu/range.h"
#include "hw/isa/isa.h"
#include "hw/sysbus.h"
@ -525,6 +526,43 @@ static const MemoryRegionOps ich9_rst_cnt_ops = {
.endianness = DEVICE_LITTLE_ENDIAN
};
Object *ich9_lpc_find(void)
{
bool ambig;
Object *o = object_resolve_path_type("", TYPE_ICH9_LPC_DEVICE, &ambig);
if (ambig) {
return NULL;
}
return o;
}
static void ich9_lpc_get_sci_int(Object *obj, Visitor *v,
void *opaque, const char *name,
Error **errp)
{
ICH9LPCState *lpc = ICH9_LPC_DEVICE(obj);
uint32_t value = ich9_lpc_sci_irq(lpc);
visit_type_uint32(v, &value, name, errp);
}
static void ich9_lpc_add_properties(ICH9LPCState *lpc)
{
static const uint8_t acpi_enable_cmd = ICH9_APM_ACPI_ENABLE;
static const uint8_t acpi_disable_cmd = ICH9_APM_ACPI_DISABLE;
object_property_add(OBJECT(lpc), ACPI_PM_PROP_SCI_INT, "uint32",
ich9_lpc_get_sci_int,
NULL, NULL, NULL, NULL);
object_property_add_uint8_ptr(OBJECT(lpc), ACPI_PM_PROP_ACPI_ENABLE_CMD,
&acpi_enable_cmd, NULL);
object_property_add_uint8_ptr(OBJECT(lpc), ACPI_PM_PROP_ACPI_DISABLE_CMD,
&acpi_disable_cmd, NULL);
ich9_pm_add_properties(OBJECT(lpc), &lpc->pm, NULL);
}
static int ich9_lpc_initfn(PCIDevice *d)
{
ICH9LPCState *lpc = ICH9_LPC_DEVICE(d);
@ -552,6 +590,8 @@ static int ich9_lpc_initfn(PCIDevice *d)
ICH9_RST_CNT_IOPORT, &lpc->rst_cnt_mem,
1);
ich9_lpc_add_properties(lpc);
return 0;
}

View File

@ -185,7 +185,7 @@ static void pm_update_sci(VT686PMState *s)
ACPI_BITMASK_POWER_BUTTON_ENABLE |
ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
ACPI_BITMASK_TIMER_ENABLE)) != 0);
qemu_set_irq(s->dev.irq[0], sci_level);
pci_set_irq(&s->dev, sci_level);
/* schedule a timer interruption if needed */
acpi_pm_tmr_update(&s->ar, (s->ar.pm1.evt.en & ACPI_BITMASK_TIMER_ENABLE) &&
!(pmsts & ACPI_BITMASK_TIMER_STATUS));

View File

@ -73,7 +73,7 @@ static inline void hwsetup_free(HWSetup *hw)
static inline void hwsetup_create_rom(HWSetup *hw,
hwaddr base)
{
rom_add_blob("hwsetup", hw->data, TARGET_PAGE_SIZE, base);
rom_add_blob("hwsetup", hw->data, TARGET_PAGE_SIZE, base, NULL, NULL, NULL);
}
static inline void hwsetup_add_u8(HWSetup *hw, uint8_t u)

View File

@ -133,7 +133,7 @@ static void ivshmem_update_irq(IVShmemState *s, int val)
isr ? 1 : 0, s->intrstatus, s->intrmask);
}
qemu_set_irq(d->irq[0], (isr != 0));
pci_set_irq(d, (isr != 0));
}
static void ivshmem_IntrMask_write(IVShmemState *s, uint32_t val)

View File

@ -117,8 +117,19 @@ void pvpanic_init(ISABus *bus)
isa_create_simple(bus, TYPE_ISA_PVPANIC_DEVICE);
}
#define PVPANIC_IOPORT_PROP "ioport"
uint16_t pvpanic_port(void)
{
Object *o = object_resolve_path_type("", TYPE_ISA_PVPANIC_DEVICE, NULL);
if (!o) {
return 0;
}
return object_property_get_int(o, PVPANIC_IOPORT_PROP, NULL);
}
static Property pvpanic_isa_properties[] = {
DEFINE_PROP_UINT16("ioport", PVPanicState, ioport, 0x505),
DEFINE_PROP_UINT16(PVPANIC_IOPORT_PROP, PVPanicState, ioport, 0x505),
DEFINE_PROP_END_OF_LIST(),
};

View File

@ -302,7 +302,7 @@ static void vfio_intx_interrupt(void *opaque)
'A' + vdev->intx.pin);
vdev->intx.pending = true;
qemu_set_irq(vdev->pdev.irq[vdev->intx.pin], 1);
pci_irq_assert(&vdev->pdev);
vfio_mmap_set_enabled(vdev, false);
if (vdev->intx.mmap_timeout) {
timer_mod(vdev->intx.mmap_timer,
@ -320,7 +320,7 @@ static void vfio_eoi(VFIODevice *vdev)
vdev->host.bus, vdev->host.slot, vdev->host.function);
vdev->intx.pending = false;
qemu_set_irq(vdev->pdev.irq[vdev->intx.pin], 0);
pci_irq_deassert(&vdev->pdev);
vfio_unmask_intx(vdev);
}
@ -346,7 +346,7 @@ static void vfio_enable_intx_kvm(VFIODevice *vdev)
qemu_set_fd_handler(irqfd.fd, NULL, NULL, vdev);
vfio_mask_intx(vdev);
vdev->intx.pending = false;
qemu_set_irq(vdev->pdev.irq[vdev->intx.pin], 0);
pci_irq_deassert(&vdev->pdev);
/* Get an eventfd for resample/unmask */
if (event_notifier_init(&vdev->intx.unmask, 0)) {
@ -422,7 +422,7 @@ static void vfio_disable_intx_kvm(VFIODevice *vdev)
*/
vfio_mask_intx(vdev);
vdev->intx.pending = false;
qemu_set_irq(vdev->pdev.irq[vdev->intx.pin], 0);
pci_irq_deassert(&vdev->pdev);
/* Tell KVM to stop listening for an INTx irqfd */
if (kvm_vm_ioctl(kvm_state, KVM_IRQFD, &irqfd)) {
@ -493,6 +493,7 @@ static int vfio_enable_intx(VFIODevice *vdev)
vfio_disable_interrupts(vdev);
vdev->intx.pin = pin - 1; /* Pin A (1) -> irq[0] */
pci_config_set_interrupt_pin(vdev->pdev.config, pin);
#ifdef CONFIG_KVM
/*
@ -552,7 +553,7 @@ static void vfio_disable_intx(VFIODevice *vdev)
vfio_disable_intx_kvm(vdev);
vfio_disable_irqindex(vdev, VFIO_PCI_INTX_IRQ_INDEX);
vdev->intx.pending = false;
qemu_set_irq(vdev->pdev.irq[vdev->intx.pin], 0);
pci_irq_deassert(&vdev->pdev);
vfio_mmap_set_enabled(vdev, true);
fd = event_notifier_get_fd(&vdev->intx.interrupt);

View File

@ -328,7 +328,7 @@ set_interrupt_cause(E1000State *s, int index, uint32_t val)
}
s->mit_irq_level = (pending_ints != 0);
qemu_set_irq(d->irq[0], s->mit_irq_level);
pci_set_irq(d, s->mit_irq_level);
}
static void

View File

@ -409,7 +409,7 @@ static void disable_interrupt(EEPRO100State * s)
{
if (s->int_stat) {
TRACE(INT, logout("interrupt disabled\n"));
qemu_irq_lower(s->dev.irq[0]);
pci_irq_deassert(&s->dev);
s->int_stat = 0;
}
}
@ -418,7 +418,7 @@ static void enable_interrupt(EEPRO100State * s)
{
if (!s->int_stat) {
TRACE(INT, logout("interrupt enabled\n"));
qemu_irq_raise(s->dev.irq[0]);
pci_irq_assert(&s->dev);
s->int_stat = 1;
}
}

View File

@ -731,7 +731,7 @@ static int pci_ne2000_init(PCIDevice *pci_dev)
s = &d->ne2000;
ne2000_setup_io(s, DEVICE(pci_dev), 0x100);
pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io);
s->irq = d->dev.irq[0];
s->irq = pci_allocate_irq(&d->dev);
qemu_macaddr_default_if_unset(&s->c.macaddr);
ne2000_reset(s);
@ -752,6 +752,7 @@ static void pci_ne2000_exit(PCIDevice *pci_dev)
memory_region_destroy(&s->io);
qemu_del_nic(s->nic);
qemu_free_irq(s->irq);
}
static Property ne2000_properties[] = {

View File

@ -282,6 +282,7 @@ static void pci_pcnet_uninit(PCIDevice *dev)
{
PCIPCNetState *d = PCI_PCNET(dev);
qemu_free_irq(d->state.irq);
memory_region_destroy(&d->state.mmio);
memory_region_destroy(&d->io_bar);
timer_del(d->state.poll_timer);
@ -331,7 +332,7 @@ static int pci_pcnet_init(PCIDevice *pci_dev)
pci_register_bar(pci_dev, 1, 0, &s->mmio);
s->irq = pci_dev->irq[0];
s->irq = pci_allocate_irq(pci_dev);
s->phys_mem_read = pci_physical_memory_read;
s->phys_mem_write = pci_physical_memory_write;
s->dma_opaque = pci_dev;

View File

@ -716,7 +716,7 @@ static void rtl8139_update_irq(RTL8139State *s)
DPRINTF("Set IRQ to %d (%04x %04x)\n", isr ? 1 : 0, s->IntrStatus,
s->IntrMask);
qemu_set_irq(d->irq[0], (isr != 0));
pci_set_irq(d, (isr != 0));
}
static int rtl8139_RxWrap(RTL8139State *s)

View File

@ -336,7 +336,7 @@ static bool _vmxnet3_assert_interrupt_line(VMXNET3State *s, uint32_t int_idx)
}
VMW_IRPRN("Asserting line for interrupt %u", int_idx);
qemu_set_irq(d->irq[int_idx], 1);
pci_irq_assert(d);
return true;
}
@ -356,7 +356,7 @@ static void _vmxnet3_deassert_interrupt_line(VMXNET3State *s, int lidx)
assert(!s->msi_used || !msi_enabled(d));
VMW_IRPRN("Deasserting line for interrupt %u", lidx);
qemu_set_irq(d->irq[lidx], 0);
pci_irq_deassert(d);
}
static void vmxnet3_update_interrupt_line_state(VMXNET3State *s, int lidx)
@ -1299,6 +1299,12 @@ static void vmxnet3_update_features(VMXNET3State *s)
}
}
static bool vmxnet3_verify_intx(VMXNET3State *s, int intx)
{
return s->msix_used || s->msi_used || (intx ==
(pci_get_byte(s->parent_obj.config + PCI_INTERRUPT_PIN) - 1));
}
static void vmxnet3_activate_device(VMXNET3State *s)
{
int i;
@ -1332,6 +1338,7 @@ static void vmxnet3_activate_device(VMXNET3State *s)
s->event_int_idx =
VMXNET3_READ_DRV_SHARED8(s->drv_shmem, devRead.intrConf.eventIntrIdx);
assert(vmxnet3_verify_intx(s, s->event_int_idx));
VMW_CFPRN("Events interrupt line is %u", s->event_int_idx);
s->auto_int_masking =
@ -1364,6 +1371,7 @@ static void vmxnet3_activate_device(VMXNET3State *s)
/* Read interrupt number for this TX queue */
s->txq_descr[i].intr_idx =
VMXNET3_READ_TX_QUEUE_DESCR8(qdescr_pa, conf.intrIdx);
assert(vmxnet3_verify_intx(s, s->txq_descr[i].intr_idx));
VMW_CFPRN("TX Queue %d interrupt: %d", i, s->txq_descr[i].intr_idx);
@ -1411,6 +1419,7 @@ static void vmxnet3_activate_device(VMXNET3State *s)
/* Read interrupt number for this RX queue */
s->rxq_descr[i].intr_idx =
VMXNET3_READ_TX_QUEUE_DESCR8(qd_pa, conf.intrIdx);
assert(vmxnet3_verify_intx(s, s->rxq_descr[i].intr_idx));
VMW_CFPRN("RX Queue %d interrupt: %d", i, s->rxq_descr[i].intr_idx);

View File

@ -42,6 +42,7 @@ typedef struct FWCfgEntry {
uint8_t *data;
void *callback_opaque;
FWCfgCallback callback;
FWCfgReadCallback read_callback;
} FWCfgEntry;
struct FWCfgState {
@ -249,8 +250,12 @@ static uint8_t fw_cfg_read(FWCfgState *s)
if (s->cur_entry == FW_CFG_INVALID || !e->data || s->cur_offset >= e->len)
ret = 0;
else
else {
if (e->read_callback) {
e->read_callback(e->callback_opaque, s->cur_offset);
}
ret = e->data[s->cur_offset++];
}
trace_fw_cfg_read(s, ret);
return ret;
@ -381,7 +386,10 @@ static const VMStateDescription vmstate_fw_cfg = {
}
};
void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len)
static void fw_cfg_add_bytes_read_callback(FWCfgState *s, uint16_t key,
FWCfgReadCallback callback,
void *callback_opaque,
void *data, size_t len)
{
int arch = !!(key & FW_CFG_ARCH_LOCAL);
@ -391,6 +399,13 @@ void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len)
s->entries[arch][key].data = data;
s->entries[arch][key].len = (uint32_t)len;
s->entries[arch][key].read_callback = callback;
s->entries[arch][key].callback_opaque = callback_opaque;
}
void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len)
{
fw_cfg_add_bytes_read_callback(s, key, NULL, NULL, data, len);
}
void fw_cfg_add_string(FWCfgState *s, uint16_t key, const char *value)
@ -444,8 +459,9 @@ void fw_cfg_add_callback(FWCfgState *s, uint16_t key, FWCfgCallback callback,
s->entries[arch][key].callback = callback;
}
void fw_cfg_add_file(FWCfgState *s, const char *filename,
void *data, size_t len)
void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
FWCfgReadCallback callback, void *callback_opaque,
void *data, size_t len)
{
int i, index;
size_t dsize;
@ -459,7 +475,8 @@ void fw_cfg_add_file(FWCfgState *s, const char *filename,
index = be32_to_cpu(s->files->count);
assert(index < FW_CFG_FILE_SLOTS);
fw_cfg_add_bytes(s, FW_CFG_FILE_FIRST + index, data, len);
fw_cfg_add_bytes_read_callback(s, FW_CFG_FILE_FIRST + index,
callback, callback_opaque, data, len);
pstrcpy(s->files->f[index].name, sizeof(s->files->f[index].name),
filename);
@ -477,6 +494,12 @@ void fw_cfg_add_file(FWCfgState *s, const char *filename,
s->files->count = cpu_to_be32(index+1);
}
void fw_cfg_add_file(FWCfgState *s, const char *filename,
void *data, size_t len)
{
fw_cfg_add_file_callback(s, filename, NULL, NULL, data, len);
}
static void fw_cfg_machine_ready(struct Notifier *n, void *data)
{
size_t len;

View File

@ -53,6 +53,7 @@ static int pci_bridge_dev_initfn(PCIDevice *dev)
if (err) {
goto bridge_error;
}
dev->config[PCI_INTERRUPT_PIN] = 0x1;
memory_region_init(&bridge_dev->bar, OBJECT(dev), "shpc-bar", shpc_bar_size(dev));
err = shpc_init(dev, &br->sec_bus, &bridge_dev->bar, 0);
if (err) {
@ -73,7 +74,6 @@ static int pci_bridge_dev_initfn(PCIDevice *dev)
* Check whether that works well. */
pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY |
PCI_BASE_ADDRESS_MEM_TYPE_64, &bridge_dev->bar);
dev->config[PCI_INTERRUPT_PIN] = 0x1;
return 0;
msi_error:
slotid_cap_cleanup(dev);

View File

@ -416,6 +416,14 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state,
return b;
}
PCIBus *find_i440fx(void)
{
PCIHostState *s = OBJECT_CHECK(PCIHostState,
object_resolve_path("/machine/i440fx", NULL),
TYPE_PCI_HOST_BRIDGE);
return s ? s->bus : NULL;
}
/* PIIX3 PCI to ISA bridge */
static void piix3_set_irq_pic(PIIX3State *piix3, int pic_irq)
{

View File

@ -109,8 +109,18 @@ static void q35_host_get_pci_hole64_end(Object *obj, Visitor *v,
visit_type_uint64(v, &w64.end, name, errp);
}
static void q35_host_get_mmcfg_size(Object *obj, Visitor *v,
void *opaque, const char *name,
Error **errp)
{
PCIExpressHost *e = PCIE_HOST_BRIDGE(obj);
uint32_t value = e->size;
visit_type_uint32(v, &value, name, errp);
}
static Property mch_props[] = {
DEFINE_PROP_UINT64("MCFG", Q35PCIHost, parent_obj.base_addr,
DEFINE_PROP_UINT64(PCIE_HOST_MCFG_BASE, Q35PCIHost, parent_obj.base_addr,
MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT),
DEFINE_PROP_SIZE(PCI_HOST_PROP_PCI_HOLE64_SIZE, Q35PCIHost,
mch.pci_hole64_size, DEFAULT_PCI_HOLE64_SIZE),
@ -160,6 +170,10 @@ static void q35_host_initfn(Object *obj)
q35_host_get_pci_hole64_end,
NULL, NULL, NULL, NULL);
object_property_add(obj, PCIE_HOST_MCFG_SIZE, "int",
q35_host_get_mmcfg_size,
NULL, NULL, NULL, NULL);
/* Leave enough space for the biggest MCFG BAR */
/* TODO: this matches current bios behaviour, but
* it's not a power of two, which means an MTRR
@ -375,6 +389,16 @@ static int mch_init(PCIDevice *d)
return 0;
}
uint64_t mch_mcfg_base(void)
{
bool ambiguous;
Object *o = object_resolve_path_type("", TYPE_MCH_PCI_DEVICE, &ambiguous);
if (!o) {
return 0;
}
return MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT;
}
static void mch_class_init(ObjectClass *klass, void *data)
{
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);

View File

@ -83,7 +83,7 @@ static const TypeInfo pcie_bus_info = {
static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num);
static void pci_update_mappings(PCIDevice *d);
static void pci_set_irq(void *opaque, int irq_num, int level);
static void pci_irq_handler(void *opaque, int irq_num, int level);
static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom);
static void pci_del_option_rom(PCIDevice *pdev);
@ -161,7 +161,7 @@ void pci_device_deassert_intx(PCIDevice *dev)
{
int i;
for (i = 0; i < PCI_NUM_PINS; ++i) {
qemu_set_irq(dev->irq[i], 0);
pci_irq_handler(dev, i, 0);
}
}
@ -283,6 +283,24 @@ const char *pci_root_bus_path(PCIDevice *dev)
return rootbus->qbus.name;
}
static uint64_t master_abort_mem_read(void *opaque, hwaddr addr, unsigned size)
{
return -1ULL;
}
static void master_abort_mem_write(void *opaque, hwaddr addr, uint64_t val,
unsigned size)
{
}
static const MemoryRegionOps master_abort_mem_ops = {
.read = master_abort_mem_read,
.write = master_abort_mem_write,
.endianness = DEVICE_LITTLE_ENDIAN,
};
#define MASTER_ABORT_MEM_PRIORITY INT_MIN
static void pci_bus_init(PCIBus *bus, DeviceState *parent,
const char *name,
MemoryRegion *address_space_mem,
@ -294,6 +312,14 @@ static void pci_bus_init(PCIBus *bus, DeviceState *parent,
bus->address_space_mem = address_space_mem;
bus->address_space_io = address_space_io;
memory_region_init_io(&bus->master_abort_mem, OBJECT(bus),
&master_abort_mem_ops, bus, "pci-master-abort",
memory_region_size(bus->address_space_mem));
memory_region_add_subregion_overlap(bus->address_space_mem,
0, &bus->master_abort_mem,
MASTER_ABORT_MEM_PRIORITY);
/* host bridge */
QLIST_INIT(&bus->child);
@ -863,14 +889,12 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
pci_dev->config_read = config_read;
pci_dev->config_write = config_write;
bus->devices[devfn] = pci_dev;
pci_dev->irq = qemu_allocate_irqs(pci_set_irq, pci_dev, PCI_NUM_PINS);
pci_dev->version_id = 2; /* Current pci device vmstate version */
return pci_dev;
}
static void do_pci_unregister_device(PCIDevice *pci_dev)
{
qemu_free_irqs(pci_dev->irq);
pci_dev->bus->devices[pci_dev->devfn] = NULL;
pci_config_free(pci_dev);
@ -1175,7 +1199,7 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
/* generic PCI irq support */
/* 0 <= irq_num <= 3. level must be 0 or 1 */
static void pci_set_irq(void *opaque, int irq_num, int level)
static void pci_irq_handler(void *opaque, int irq_num, int level)
{
PCIDevice *pci_dev = opaque;
int change;
@ -1191,6 +1215,24 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
pci_change_irq_level(pci_dev, irq_num, change);
}
static inline int pci_intx(PCIDevice *pci_dev)
{
return pci_get_byte(pci_dev->config + PCI_INTERRUPT_PIN) - 1;
}
qemu_irq pci_allocate_irq(PCIDevice *pci_dev)
{
int intx = pci_intx(pci_dev);
return qemu_allocate_irq(pci_irq_handler, pci_dev, intx);
}
void pci_set_irq(PCIDevice *pci_dev, int level)
{
int intx = pci_intx(pci_dev);
pci_irq_handler(pci_dev, intx, level);
}
/* Special hooks used by device assignment */
void pci_bus_set_route_irq_fn(PCIBus *bus, pci_route_irq_fn route_intx_to_irq)
{
@ -2264,7 +2306,7 @@ static void pci_dev_get_w64(PCIBus *b, PCIDevice *dev, void *opaque)
Range *range = opaque;
PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
uint16_t cmd = pci_get_word(dev->config + PCI_COMMAND);
int r;
int i;
if (!(cmd & PCI_COMMAND_MEMORY)) {
return;
@ -2283,17 +2325,21 @@ static void pci_dev_get_w64(PCIBus *b, PCIDevice *dev, void *opaque)
range_extend(range, &pref_range);
}
}
for (r = 0; r < PCI_NUM_REGIONS; ++r) {
PCIIORegion *region = &dev->io_regions[r];
for (i = 0; i < PCI_NUM_REGIONS; ++i) {
PCIIORegion *r = &dev->io_regions[i];
Range region_range;
if (!region->size ||
(region->type & PCI_BASE_ADDRESS_SPACE_IO) ||
!(region->type & PCI_BASE_ADDRESS_MEM_TYPE_64)) {
if (!r->size ||
(r->type & PCI_BASE_ADDRESS_SPACE_IO) ||
!(r->type & PCI_BASE_ADDRESS_MEM_TYPE_64)) {
continue;
}
region_range.begin = pci_bar_address(dev, i, r->type, r->size);
region_range.end = region_range.begin + r->size;
if (region_range.begin == PCI_BAR_UNMAPPED) {
continue;
}
region_range.begin = pci_get_quad(dev->config + pci_bar(dev, r));
region_range.end = region_range.begin + region->size;
region_range.begin = MAX(region_range.begin, 0x1ULL << 32);

View File

@ -187,7 +187,7 @@ static void hotplug_event_notify(PCIDevice *dev)
} else if (msi_enabled(dev)) {
msi_notify(dev, pcie_cap_flags_get_vector(dev));
} else {
qemu_set_irq(dev->irq[dev->exp.hpev_intx], dev->exp.hpev_notified);
pci_set_irq(dev, dev->exp.hpev_notified);
}
}
@ -195,7 +195,7 @@ static void hotplug_event_clear(PCIDevice *dev)
{
hotplug_event_update_event_status(dev);
if (!msix_enabled(dev) && !msi_enabled(dev) && !dev->exp.hpev_notified) {
qemu_set_irq(dev->irq[dev->exp.hpev_intx], 0);
pci_irq_deassert(dev);
}
}

View File

@ -285,7 +285,7 @@ static void pcie_aer_root_notify(PCIDevice *dev)
} else if (msi_enabled(dev)) {
msi_notify(dev, pcie_aer_root_get_vector(dev));
} else {
qemu_set_irq(dev->irq[dev->exp.aer_intx], 1);
pci_irq_assert(dev);
}
}
@ -768,7 +768,7 @@ void pcie_aer_root_write_config(PCIDevice *dev,
uint32_t root_cmd = pci_get_long(aer_cap + PCI_ERR_ROOT_COMMAND);
/* 6.2.4.1.2 Interrupt Generation */
if (!msix_enabled(dev) && !msi_enabled(dev)) {
qemu_set_irq(dev->irq[dev->exp.aer_intx], !!(root_cmd & enabled_cmd));
pci_set_irq(dev, !!(root_cmd & enabled_cmd));
return;
}

View File

@ -24,27 +24,6 @@
#include "hw/pci/pcie_host.h"
#include "exec/address-spaces.h"
/*
* PCI express mmcfig address
* bit 20 - 28: bus number
* bit 15 - 19: device number
* bit 12 - 14: function number
* bit 0 - 11: offset in configuration space of a given device
*/
#define PCIE_MMCFG_SIZE_MAX (1ULL << 28)
#define PCIE_MMCFG_SIZE_MIN (1ULL << 20)
#define PCIE_MMCFG_BUS_BIT 20
#define PCIE_MMCFG_BUS_MASK 0x1ff
#define PCIE_MMCFG_DEVFN_BIT 12
#define PCIE_MMCFG_DEVFN_MASK 0xff
#define PCIE_MMCFG_CONFOFFSET_MASK 0xfff
#define PCIE_MMCFG_BUS(addr) (((addr) >> PCIE_MMCFG_BUS_BIT) & \
PCIE_MMCFG_BUS_MASK)
#define PCIE_MMCFG_DEVFN(addr) (((addr) >> PCIE_MMCFG_DEVFN_BIT) & \
PCIE_MMCFG_DEVFN_MASK)
#define PCIE_MMCFG_CONFOFFSET(addr) ((addr) & PCIE_MMCFG_CONFOFFSET_MASK)
/* a helper function to get a PCIDevice for a given mmconfig address */
static inline PCIDevice *pcie_dev_find_by_mmcfg_addr(PCIBus *s,
uint32_t mmcfg_addr)
@ -104,9 +83,6 @@ static const MemoryRegionOps pcie_mmcfg_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
/* pcie_host::base_addr == PCIE_BASE_ADDR_UNMAPPED when it isn't mapped. */
#define PCIE_BASE_ADDR_UNMAPPED ((hwaddr)-1ULL)
int pcie_host_init(PCIExpressHost *e)
{
e->base_addr = PCIE_BASE_ADDR_UNMAPPED;

View File

@ -172,7 +172,7 @@ static void shpc_interrupt_update(PCIDevice *d)
if (msi_enabled(d) && shpc->msi_requested != level)
msi_notify(d, 0);
else
qemu_set_irq(d->irq[0], level);
pci_set_irq(d, level);
shpc->msi_requested = level;
}

View File

@ -361,7 +361,7 @@ static int esp_pci_scsi_init(PCIDevice *dev)
"esp-io", 0x80);
pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->io);
s->irq = dev->irq[0];
s->irq = pci_allocate_irq(dev);
scsi_bus_new(&s->bus, sizeof(s->bus), d, &esp_pci_scsi_info, NULL);
if (!d->hotplugged) {
@ -378,6 +378,7 @@ static void esp_pci_scsi_uninit(PCIDevice *d)
{
PCIESPState *pci = PCI_ESP(d);
qemu_free_irq(pci->esp.irq);
memory_region_destroy(&pci->io);
}

View File

@ -437,7 +437,7 @@ static void lsi_update_irq(LSIState *s)
level, s->dstat, s->sist1, s->sist0);
last_level = level;
}
qemu_set_irq(d->irq[0], level);
pci_set_irq(d, level);
if (!level && lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON)) {
DPRINTF("Handled IRQs & disconnected, looking for pending "

View File

@ -535,7 +535,7 @@ static void megasas_complete_frame(MegasasState *s, uint64_t context)
msix_notify(pci_dev, 0);
} else {
trace_megasas_irq_raise();
qemu_irq_raise(pci_dev->irq[0]);
pci_irq_assert(pci_dev);
}
}
} else {
@ -1936,7 +1936,7 @@ static void megasas_mmio_write(void *opaque, hwaddr addr,
s->intr_mask = val;
if (!megasas_intr_enabled(s) && !msix_enabled(pci_dev)) {
trace_megasas_irq_lower();
qemu_irq_lower(pci_dev->irq[0]);
pci_irq_deassert(pci_dev);
}
if (megasas_intr_enabled(s)) {
trace_megasas_intr_enabled();
@ -1952,7 +1952,7 @@ static void megasas_mmio_write(void *opaque, hwaddr addr,
stl_le_phys(s->producer_pa, s->reply_queue_head);
if (!msix_enabled(pci_dev)) {
trace_megasas_irq_lower();
qemu_irq_lower(pci_dev->irq[0]);
pci_irq_deassert(pci_dev);
}
}
break;

View File

@ -330,7 +330,7 @@ pvscsi_update_irq_status(PVSCSIState *s)
return;
}
qemu_set_irq(d->irq[0], !!should_raise);
pci_set_irq(d, !!should_raise);
}
static void

View File

@ -757,6 +757,11 @@ static void hpet_device_class_init(ObjectClass *klass, void *data)
dc->props = hpet_device_properties;
}
bool hpet_find(void)
{
return object_resolve_path_type("", TYPE_HPET, NULL);
}
static const TypeInfo hpet_device_info = {
.name = TYPE_HPET,
.parent = TYPE_SYS_BUS_DEVICE,

View File

@ -60,7 +60,7 @@ static int usb_ehci_pci_initfn(PCIDevice *dev)
pci_conf[0x6e] = 0x00;
pci_conf[0x6f] = 0xc0; /* USBLEFCTLSTS */
s->irq = dev->irq[3];
s->irq = pci_allocate_irq(dev);
s->as = pci_get_address_space(dev);
usb_ehci_realize(s, DEVICE(dev), NULL);

View File

@ -1946,7 +1946,7 @@ static int usb_ohci_initfn_pci(PCIDevice *dev)
pci_get_address_space(dev)) != 0) {
return -1;
}
ohci->state.irq = dev->irq[0];
ohci->state.irq = pci_allocate_irq(dev);
pci_register_bar(dev, 0, 0, &ohci->state.mem);
return 0;

View File

@ -164,7 +164,6 @@ struct UHCIState {
/* Interrupts that should be raised at the end of the current frame. */
uint32_t pending_int_mask;
int irq_pin;
/* Active packets */
QTAILQ_HEAD(, UHCIQueue) queues;
@ -381,7 +380,7 @@ static void uhci_update_irq(UHCIState *s)
} else {
level = 0;
}
qemu_set_irq(s->dev.irq[s->irq_pin], level);
pci_set_irq(&s->dev, level);
}
static void uhci_reset(void *opaque)
@ -1240,8 +1239,7 @@ static int usb_uhci_common_initfn(PCIDevice *dev)
/* TODO: reset value should be 0. */
pci_conf[USB_SBRN] = USB_RELEASE_1; // release number
s->irq_pin = u->info.irq_pin;
pci_config_set_interrupt_pin(pci_conf, s->irq_pin + 1);
pci_config_set_interrupt_pin(pci_conf, u->info.irq_pin + 1);
if (s->masterbus) {
USBPort *ports[NB_PORTS];

View File

@ -449,7 +449,6 @@ struct XHCIState {
/*< public >*/
USBBus bus;
qemu_irq irq;
MemoryRegion mem;
MemoryRegion mem_cap;
MemoryRegion mem_oper;
@ -739,7 +738,7 @@ static void xhci_intx_update(XHCIState *xhci)
}
trace_usb_xhci_irq_intx(level);
qemu_set_irq(xhci->irq, level);
pci_set_irq(pci_dev, level);
}
static void xhci_msix_update(XHCIState *xhci, int v)
@ -797,7 +796,7 @@ static void xhci_intr_raise(XHCIState *xhci, int v)
if (v == 0) {
trace_usb_xhci_irq_intx(1);
qemu_set_irq(xhci->irq, 1);
pci_irq_assert(pci_dev);
}
}
@ -3433,8 +3432,6 @@ static int usb_xhci_initfn(struct PCIDevice *dev)
xhci->mfwrap_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, xhci_mfwrap_timer, xhci);
xhci->irq = dev->irq[0];
memory_region_init(&xhci->mem, OBJECT(xhci), "xhci", LEN_REGS);
memory_region_init_io(&xhci->mem_cap, OBJECT(xhci), &xhci_cap_ops, xhci,
"capabilities", LEN_CAP);

View File

@ -116,7 +116,7 @@ static void virtio_pci_notify(DeviceState *d, uint16_t vector)
if (msix_enabled(&proxy->pci_dev))
msix_notify(&proxy->pci_dev, vector);
else
qemu_set_irq(proxy->pci_dev.irq[0], proxy->vdev->isr & 1);
pci_set_irq(&proxy->pci_dev, proxy->vdev->isr & 1);
}
static void virtio_pci_save_config(DeviceState *d, QEMUFile *f)
@ -362,7 +362,7 @@ static uint32_t virtio_ioport_read(VirtIOPCIProxy *proxy, uint32_t addr)
/* reading from the ISR also clears it. */
ret = vdev->isr;
vdev->isr = 0;
qemu_set_irq(proxy->pci_dev.irq[0], 0);
pci_irq_deassert(&proxy->pci_dev);
break;
case VIRTIO_MSI_CONFIG_VECTOR:
ret = vdev->config_vector;

View File

@ -153,7 +153,7 @@ struct MemoryRegion {
bool flush_coalesced_mmio;
MemoryRegion *alias;
hwaddr alias_offset;
unsigned priority;
int priority;
bool may_overlap;
QTAILQ_HEAD(subregions, MemoryRegion) subregions;
QTAILQ_ENTRY(MemoryRegion) subregions_link;
@ -779,7 +779,7 @@ void memory_region_add_subregion(MemoryRegion *mr,
void memory_region_add_subregion_overlap(MemoryRegion *mr,
hwaddr offset,
MemoryRegion *subregion,
unsigned priority);
int priority);
/**
* memory_region_get_ram_addr: Get the ram address associated with a memory

View File

@ -165,6 +165,10 @@ extern int acpi_enabled;
extern char unsigned *acpi_tables;
extern size_t acpi_tables_len;
uint8_t *acpi_table_first(void);
uint8_t *acpi_table_next(uint8_t *current);
unsigned acpi_table_len(void *current);
void acpi_table_add(const QemuOpts *opts, Error **errp);
void acpi_table_add_builtin(const QemuOpts *opts, Error **errp);
#endif /* !QEMU_HW_ACPI_H */

View File

@ -49,4 +49,6 @@ void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
void ich9_pm_iospace_update(ICH9LPCPMRegs *pm, uint32_t pm_io_base);
extern const VMStateDescription vmstate_ich9_pm;
void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp);
#endif /* HW_ACPI_ICH9_H */

8
include/hw/acpi/piix4.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef HW_ACPI_PIIX4_H
#define HW_ACPI_PIIX4_H
#include "qemu/typedefs.h"
Object *piix4_pm_find(void);
#endif

View File

@ -66,6 +66,8 @@ typedef struct ICH9LPCState {
qemu_irq *ioapic;
} ICH9LPCState;
Object *ich9_lpc_find(void);
#define Q35_MASK(bit, ms_bit, ls_bit) \
((uint##bit##_t)(((1ULL << ((ms_bit) + 1)) - 1) & ~((1ULL << ls_bit) - 1)))

View File

@ -9,6 +9,9 @@
#include "hw/i386/ioapic.h"
#include "qemu/range.h"
#include "qemu/bitmap.h"
#include "sysemu/sysemu.h"
#include "hw/pci/pci.h"
/* PC-style peripherals (also used by other machines). */
@ -17,10 +20,27 @@ typedef struct PcPciInfo {
Range w64;
} PcPciInfo;
#define ACPI_PM_PROP_S3_DISABLED "disable_s3"
#define ACPI_PM_PROP_S4_DISABLED "disable_s4"
#define ACPI_PM_PROP_S4_VAL "s4_val"
#define ACPI_PM_PROP_SCI_INT "sci_int"
#define ACPI_PM_PROP_ACPI_ENABLE_CMD "acpi_enable_cmd"
#define ACPI_PM_PROP_ACPI_DISABLE_CMD "acpi_disable_cmd"
#define ACPI_PM_PROP_PM_IO_BASE "pm_io_base"
#define ACPI_PM_PROP_GPE0_BLK "gpe0_blk"
#define ACPI_PM_PROP_GPE0_BLK_LEN "gpe0_blk_len"
struct PcGuestInfo {
bool has_pci_info;
bool isapc_ram_fw;
hwaddr ram_size;
unsigned apic_id_limit;
bool apic_xrupt_override;
uint64_t numa_nodes;
uint64_t *node_mem;
uint64_t *node_cpu;
FWCfgState *fw_cfg;
bool has_acpi_build;
};
/* parallel.c */
@ -173,6 +193,7 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn,
MemoryRegion *pci_memory,
MemoryRegion *ram_memory);
PCIBus *find_i440fx(void);
/* piix4.c */
extern PCIDevice *piix4_dev;
int piix4_init(PCIBus *bus, ISABus **isa_bus, int devfn);
@ -215,6 +236,7 @@ void pc_system_firmware_init(MemoryRegion *rom_memory,
/* pvpanic.c */
void pvpanic_init(ISABus *bus);
uint16_t pvpanic_port(void);
/* e820 types */
#define E820_RAM 1

View File

@ -30,6 +30,12 @@ static inline void qemu_irq_pulse(qemu_irq irq)
*/
qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n);
/*
* Allocates a single IRQ. The irq is assigned with a handler, an opaque
* data and the interrupt number.
*/
qemu_irq qemu_allocate_irq(qemu_irq_handler handler, void *opaque, int n);
/* Extends an Array of IRQs. Old IRQs have their handlers and opaque data
* preserved. New IRQs are assigned the argument handler and opaque data.
*/
@ -37,6 +43,7 @@ qemu_irq *qemu_extend_irqs(qemu_irq *old, int n_old, qemu_irq_handler handler,
void *opaque, int n);
void qemu_free_irqs(qemu_irq *s);
void qemu_free_irq(qemu_irq irq);
/* Returns a new IRQ with opposite polarity. */
qemu_irq qemu_irq_invert(qemu_irq irq);

View File

@ -40,11 +40,13 @@ extern bool rom_file_in_ram;
int rom_add_file(const char *file, const char *fw_dir,
hwaddr addr, int32_t bootindex);
int rom_add_blob(const char *name, const void *blob, size_t len,
hwaddr addr);
void *rom_add_blob(const char *name, const void *blob, size_t len,
hwaddr addr, const char *fw_file_name,
FWCfgReadCallback fw_callback, void *callback_opaque);
int rom_add_elf_program(const char *name, void *data, size_t datasize,
size_t romsize, hwaddr addr);
int rom_load_all(void);
void rom_load_done(void);
void rom_set_fw(FWCfgState *f);
int rom_copy(uint8_t *dest, hwaddr addr, size_t size);
void *rom_ptr(hwaddr addr);
@ -53,7 +55,7 @@ void do_info_roms(Monitor *mon, const QDict *qdict);
#define rom_add_file_fixed(_f, _a, _i) \
rom_add_file(_f, NULL, _a, _i)
#define rom_add_blob_fixed(_f, _b, _l, _a) \
rom_add_blob(_f, _b, _l, _a)
(rom_add_blob(_f, _b, _l, _a, NULL, NULL, NULL) ? 0 : -1)
#define PC_ROM_MIN_VGA 0xc0000
#define PC_ROM_MIN_OPTION 0xc8000

View File

@ -46,12 +46,14 @@
#define FW_CFG_INVALID 0xffff
#define FW_CFG_MAX_FILE_PATH 56
#ifndef NO_QEMU_PROTOS
typedef struct FWCfgFile {
uint32_t size; /* file size */
uint16_t select; /* write this to 0x510 to read it */
uint16_t reserved;
char name[56];
char name[FW_CFG_MAX_FILE_PATH];
} FWCfgFile;
typedef struct FWCfgFiles {
@ -60,6 +62,7 @@ typedef struct FWCfgFiles {
} FWCfgFiles;
typedef void (*FWCfgCallback)(void *opaque, uint8_t *data);
typedef void (*FWCfgReadCallback)(void *opaque, uint32_t offset);
void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len);
void fw_cfg_add_string(FWCfgState *s, uint16_t key, const char *value);
@ -70,6 +73,9 @@ void fw_cfg_add_callback(FWCfgState *s, uint16_t key, FWCfgCallback callback,
void *callback_opaque, void *data, size_t len);
void fw_cfg_add_file(FWCfgState *s, const char *filename, void *data,
size_t len);
void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
FWCfgReadCallback callback, void *callback_opaque,
void *data, size_t len);
FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
hwaddr crl_addr, hwaddr data_addr);

View File

@ -156,4 +156,6 @@ typedef struct Q35PCIHost {
#define MCH_PCIE_DEV 1
#define MCH_PCIE_FUNC 0
uint64_t mch_mcfg_base(void);
#endif /* HW_Q35_H */

View File

@ -247,9 +247,6 @@ struct PCIDevice {
PCIConfigReadFunc *config_read;
PCIConfigWriteFunc *config_write;
/* IRQ objects for the INTA-INTD pins. */
qemu_irq *irq;
/* Legacy PCI VGA regions */
MemoryRegion *vga_regions[QEMU_PCI_VGA_NUM_REGIONS];
bool has_vga;
@ -632,6 +629,29 @@ PCIDevice *pci_create_simple_multifunction(PCIBus *bus, int devfn,
PCIDevice *pci_create(PCIBus *bus, int devfn, const char *name);
PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name);
qemu_irq pci_allocate_irq(PCIDevice *pci_dev);
void pci_set_irq(PCIDevice *pci_dev, int level);
static inline void pci_irq_assert(PCIDevice *pci_dev)
{
pci_set_irq(pci_dev, 1);
}
static inline void pci_irq_deassert(PCIDevice *pci_dev)
{
pci_set_irq(pci_dev, 0);
}
/*
* FIXME: PCI does not work this way.
* All the callers to this method should be fixed.
*/
static inline void pci_irq_pulse(PCIDevice *pci_dev)
{
pci_irq_assert(pci_dev);
pci_irq_deassert(pci_dev);
}
static inline int pci_is_express(const PCIDevice *d)
{
return d->cap_present & QEMU_PCI_CAP_EXPRESS;

View File

@ -23,6 +23,7 @@ struct PCIBus {
PCIDevice *parent_dev;
MemoryRegion *address_space_mem;
MemoryRegion *address_space_io;
MemoryRegion master_abort_mem;
QLIST_HEAD(, PCIBus) child; /* this will be replaced by qdev later */
QLIST_ENTRY(PCIBus) sibling;/* this will be replaced by qdev later */

View File

@ -64,15 +64,6 @@ struct PCIExpressDevice {
uint8_t exp_cap;
/* SLOT */
unsigned int hpev_intx; /* INTx for hot plug event (0-3:INT[A-D]#)
* default is 0 = INTA#
* If the chip wants to use other interrupt
* line, initialize this member with the
* desired number.
* If the chip dynamically changes this member,
* also initialize it when loaded as
* appropreately.
*/
bool hpev_notified; /* Logical AND of conditions for hot plug event.
Following 6.7.3.4:
Software Notification of Hot-Plug Events, an interrupt
@ -82,15 +73,6 @@ struct PCIExpressDevice {
/* AER */
uint16_t aer_cap;
PCIEAERLog aer_log;
unsigned int aer_intx; /* INTx for error reporting
* default is 0 = INTA#
* If the chip wants to use other interrupt
* line, initialize this member with the
* desired number.
* If the chip dynamically changes this member,
* also initialize it when loaded as
* appropreately.
*/
};
/* PCI express capability helper functions */

View File

@ -28,6 +28,12 @@
#define PCIE_HOST_BRIDGE(obj) \
OBJECT_CHECK(PCIExpressHost, (obj), TYPE_PCIE_HOST_BRIDGE)
#define PCIE_HOST_MCFG_BASE "MCFG"
#define PCIE_HOST_MCFG_SIZE "mcfg_size"
/* pcie_host::base_addr == PCIE_BASE_ADDR_UNMAPPED when it isn't mapped. */
#define PCIE_BASE_ADDR_UNMAPPED ((hwaddr)-1ULL)
struct PCIExpressHost {
PCIHostState pci;
@ -51,4 +57,25 @@ void pcie_host_mmcfg_update(PCIExpressHost *e,
hwaddr addr,
uint32_t size);
/*
* PCI express ECAM (Enhanced Configuration Address Mapping) format.
* AKA mmcfg address
* bit 20 - 28: bus number
* bit 15 - 19: device number
* bit 12 - 14: function number
* bit 0 - 11: offset in configuration space of a given device
*/
#define PCIE_MMCFG_SIZE_MAX (1ULL << 28)
#define PCIE_MMCFG_SIZE_MIN (1ULL << 20)
#define PCIE_MMCFG_BUS_BIT 20
#define PCIE_MMCFG_BUS_MASK 0x1ff
#define PCIE_MMCFG_DEVFN_BIT 12
#define PCIE_MMCFG_DEVFN_MASK 0xff
#define PCIE_MMCFG_CONFOFFSET_MASK 0xfff
#define PCIE_MMCFG_BUS(addr) (((addr) >> PCIE_MMCFG_BUS_BIT) & \
PCIE_MMCFG_BUS_MASK)
#define PCIE_MMCFG_DEVFN(addr) (((addr) >> PCIE_MMCFG_DEVFN_BIT) & \
PCIE_MMCFG_DEVFN_MASK)
#define PCIE_MMCFG_CONFOFFSET(addr) ((addr) & PCIE_MMCFG_CONFOFFSET_MASK)
#endif /* PCIE_HOST_H */

View File

@ -68,7 +68,7 @@ void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size);
void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq);
void sysbus_mmio_map(SysBusDevice *dev, int n, hwaddr addr);
void sysbus_mmio_map_overlap(SysBusDevice *dev, int n, hwaddr addr,
unsigned priority);
int priority);
void sysbus_add_io(SysBusDevice *dev, hwaddr addr,
MemoryRegion *mem);
void sysbus_del_io(SysBusDevice *dev, MemoryRegion *mem);

View File

@ -71,4 +71,6 @@ struct hpet_fw_config
} QEMU_PACKED;
extern struct hpet_fw_config hpet_cfg;
bool hpet_find(void);
#endif

View File

@ -18,9 +18,9 @@
#include <stdint.h>
#include <stdbool.h>
#include "qemu/queue.h"
#include "qapi/error.h"
struct Visitor;
struct Error;
struct TypeImpl;
typedef struct TypeImpl *Type;
@ -301,7 +301,7 @@ typedef void (ObjectPropertyAccessor)(Object *obj,
struct Visitor *v,
void *opaque,
const char *name,
struct Error **errp);
Error **errp);
/**
* ObjectPropertyRelease:
@ -790,9 +790,30 @@ void object_property_add(Object *obj, const char *name, const char *type,
ObjectPropertyAccessor *get,
ObjectPropertyAccessor *set,
ObjectPropertyRelease *release,
void *opaque, struct Error **errp);
void *opaque, Error **errp);
void object_property_del(Object *obj, const char *name, struct Error **errp);
void object_property_del(Object *obj, const char *name, Error **errp);
/**
* object_property_add_uint8_ptr:
* object_property_add_uint16_ptr:
* object_property_add_uint32_ptr:
* object_property_add_uint64_ptr:
* @obj: the object to add a property to
* @name: the name of the property
* @v: pointer to value
*
* Add an integer property in memory. This function will add a
* property of the appropriate type.
*/
void object_property_add_uint8_ptr(Object *obj, const char *name,
const uint8_t *v, Error **errp);
void object_property_add_uint16_ptr(Object *obj, const char *name,
const uint16_t *v, Error **errp);
void object_property_add_uint32_ptr(Object *obj, const char *name,
const uint32_t *v, Error **errp);
void object_property_add_uint64_ptr(Object *obj, const char *name,
const uint64_t *v, Error **Errp);
/**
* object_property_find:
@ -803,7 +824,7 @@ void object_property_del(Object *obj, const char *name, struct Error **errp);
* Look up a property for an object and return its #ObjectProperty if found.
*/
ObjectProperty *object_property_find(Object *obj, const char *name,
struct Error **errp);
Error **errp);
void object_unparent(Object *obj);
@ -818,7 +839,7 @@ void object_unparent(Object *obj);
* Reads a property from a object.
*/
void object_property_get(Object *obj, struct Visitor *v, const char *name,
struct Error **errp);
Error **errp);
/**
* object_property_set_str:
@ -829,7 +850,7 @@ void object_property_get(Object *obj, struct Visitor *v, const char *name,
* Writes a string value to a property.
*/
void object_property_set_str(Object *obj, const char *value,
const char *name, struct Error **errp);
const char *name, Error **errp);
/**
* object_property_get_str:
@ -842,7 +863,7 @@ void object_property_set_str(Object *obj, const char *value,
* The caller should free the string.
*/
char *object_property_get_str(Object *obj, const char *name,
struct Error **errp);
Error **errp);
/**
* object_property_set_link:
@ -853,7 +874,7 @@ char *object_property_get_str(Object *obj, const char *name,
* Writes an object's canonical path to a property.
*/
void object_property_set_link(Object *obj, Object *value,
const char *name, struct Error **errp);
const char *name, Error **errp);
/**
* object_property_get_link:
@ -866,7 +887,7 @@ void object_property_set_link(Object *obj, Object *value,
* string or not a valid object path).
*/
Object *object_property_get_link(Object *obj, const char *name,
struct Error **errp);
Error **errp);
/**
* object_property_set_bool:
@ -877,7 +898,7 @@ Object *object_property_get_link(Object *obj, const char *name,
* Writes a bool value to a property.
*/
void object_property_set_bool(Object *obj, bool value,
const char *name, struct Error **errp);
const char *name, Error **errp);
/**
* object_property_get_bool:
@ -889,7 +910,7 @@ void object_property_set_bool(Object *obj, bool value,
* an error occurs (including when the property value is not a bool).
*/
bool object_property_get_bool(Object *obj, const char *name,
struct Error **errp);
Error **errp);
/**
* object_property_set_int:
@ -900,7 +921,7 @@ bool object_property_get_bool(Object *obj, const char *name,
* Writes an integer value to a property.
*/
void object_property_set_int(Object *obj, int64_t value,
const char *name, struct Error **errp);
const char *name, Error **errp);
/**
* object_property_get_int:
@ -912,7 +933,7 @@ void object_property_set_int(Object *obj, int64_t value,
* an error occurs (including when the property value is not an integer).
*/
int64_t object_property_get_int(Object *obj, const char *name,
struct Error **errp);
Error **errp);
/**
* object_property_set:
@ -926,7 +947,7 @@ int64_t object_property_get_int(Object *obj, const char *name,
* Writes a property to a object.
*/
void object_property_set(Object *obj, struct Visitor *v, const char *name,
struct Error **errp);
Error **errp);
/**
* object_property_parse:
@ -938,7 +959,7 @@ void object_property_set(Object *obj, struct Visitor *v, const char *name,
* Parses a string and writes the result into a property of an object.
*/
void object_property_parse(Object *obj, const char *string,
const char *name, struct Error **errp);
const char *name, Error **errp);
/**
* object_property_print:
@ -950,7 +971,7 @@ void object_property_parse(Object *obj, const char *string,
* caller shall free the string.
*/
char *object_property_print(Object *obj, const char *name,
struct Error **errp);
Error **errp);
/**
* object_property_get_type:
@ -961,7 +982,7 @@ char *object_property_print(Object *obj, const char *name,
* Returns: The type name of the property.
*/
const char *object_property_get_type(Object *obj, const char *name,
struct Error **errp);
Error **errp);
/**
* object_get_root:
@ -1054,7 +1075,7 @@ Object *object_resolve_path_component(Object *parent, const gchar *part);
* The child object itself can be retrieved using object_property_get_link().
*/
void object_property_add_child(Object *obj, const char *name,
Object *child, struct Error **errp);
Object *child, Error **errp);
/**
* object_property_add_link:
@ -1077,7 +1098,7 @@ void object_property_add_child(Object *obj, const char *name,
*/
void object_property_add_link(Object *obj, const char *name,
const char *type, Object **child,
struct Error **errp);
Error **errp);
/**
* object_property_add_str:
@ -1092,9 +1113,9 @@ void object_property_add_link(Object *obj, const char *name,
* property of type 'string'.
*/
void object_property_add_str(Object *obj, const char *name,
char *(*get)(Object *, struct Error **),
void (*set)(Object *, const char *, struct Error **),
struct Error **errp);
char *(*get)(Object *, Error **),
void (*set)(Object *, const char *, Error **),
Error **errp);
/**
* object_property_add_bool:
@ -1108,9 +1129,9 @@ void object_property_add_str(Object *obj, const char *name,
* property of type 'bool'.
*/
void object_property_add_bool(Object *obj, const char *name,
bool (*get)(Object *, struct Error **),
void (*set)(Object *, bool, struct Error **),
struct Error **errp);
bool (*get)(Object *, Error **),
void (*set)(Object *, bool, Error **),
Error **errp);
/**
* object_child_foreach:

View File

@ -1473,7 +1473,7 @@ void memory_region_add_subregion(MemoryRegion *mr,
void memory_region_add_subregion_overlap(MemoryRegion *mr,
hwaddr offset,
MemoryRegion *subregion,
unsigned priority)
int priority)
{
subregion->may_overlap = true;
subregion->priority = priority;
@ -1506,7 +1506,7 @@ void memory_region_set_enabled(MemoryRegion *mr, bool enabled)
void memory_region_set_address(MemoryRegion *mr, hwaddr addr)
{
MemoryRegion *parent = mr->parent;
unsigned priority = mr->priority;
int priority = mr->priority;
bool may_overlap = mr->may_overlap;
if (addr == mr->addr || !parent) {

View File

@ -1344,6 +1344,66 @@ static char *qdev_get_type(Object *obj, Error **errp)
return g_strdup(object_get_typename(obj));
}
static void property_get_uint8_ptr(Object *obj, Visitor *v,
void *opaque, const char *name,
Error **errp)
{
uint8_t value = *(uint8_t *)opaque;
visit_type_uint8(v, &value, name, errp);
}
static void property_get_uint16_ptr(Object *obj, Visitor *v,
void *opaque, const char *name,
Error **errp)
{
uint16_t value = *(uint16_t *)opaque;
visit_type_uint16(v, &value, name, errp);
}
static void property_get_uint32_ptr(Object *obj, Visitor *v,
void *opaque, const char *name,
Error **errp)
{
uint32_t value = *(uint32_t *)opaque;
visit_type_uint32(v, &value, name, errp);
}
static void property_get_uint64_ptr(Object *obj, Visitor *v,
void *opaque, const char *name,
Error **errp)
{
uint64_t value = *(uint64_t *)opaque;
visit_type_uint64(v, &value, name, errp);
}
void object_property_add_uint8_ptr(Object *obj, const char *name,
const uint8_t *v, Error **errp)
{
object_property_add(obj, name, "uint8", property_get_uint8_ptr,
NULL, NULL, (void *)v, errp);
}
void object_property_add_uint16_ptr(Object *obj, const char *name,
const uint16_t *v, Error **errp)
{
object_property_add(obj, name, "uint16", property_get_uint16_ptr,
NULL, NULL, (void *)v, errp);
}
void object_property_add_uint32_ptr(Object *obj, const char *name,
const uint32_t *v, Error **errp)
{
object_property_add(obj, name, "uint32", property_get_uint32_ptr,
NULL, NULL, (void *)v, errp);
}
void object_property_add_uint64_ptr(Object *obj, const char *name,
const uint64_t *v, Error **errp)
{
object_property_add(obj, name, "uint64", property_get_uint64_ptr,
NULL, NULL, (void *)v, errp);
}
static void object_instance_init(Object *obj)
{
object_property_add_str(obj, "type", qdev_get_type, NULL, NULL);

362
scripts/acpi_extract.py Executable file
View File

@ -0,0 +1,362 @@
#!/usr/bin/python
# Copyright (C) 2011 Red Hat, Inc., Michael S. Tsirkin <mst@redhat.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, see <http://www.gnu.org/licenses/>.
# Process mixed ASL/AML listing (.lst file) produced by iasl -l
# Locate and execute ACPI_EXTRACT directives, output offset info
#
# Documentation of ACPI_EXTRACT_* directive tags:
#
# These directive tags output offset information from AML for BIOS runtime
# table generation.
# Each directive is of the form:
# ACPI_EXTRACT_<TYPE> <array_name> <Operator> (...)
# and causes the extractor to create an array
# named <array_name> with offset, in the generated AML,
# of an object of a given type in the following <Operator>.
#
# A directive must fit on a single code line.
#
# Object type in AML is verified, a mismatch causes a build failure.
#
# Directives and operators currently supported are:
# ACPI_EXTRACT_NAME_DWORD_CONST - extract a Dword Const object from Name()
# ACPI_EXTRACT_NAME_WORD_CONST - extract a Word Const object from Name()
# ACPI_EXTRACT_NAME_BYTE_CONST - extract a Byte Const object from Name()
# ACPI_EXTRACT_METHOD_STRING - extract a NameString from Method()
# ACPI_EXTRACT_NAME_STRING - extract a NameString from Name()
# ACPI_EXTRACT_PROCESSOR_START - start of Processor() block
# ACPI_EXTRACT_PROCESSOR_STRING - extract a NameString from Processor()
# ACPI_EXTRACT_PROCESSOR_END - offset at last byte of Processor() + 1
# ACPI_EXTRACT_PKG_START - start of Package block
#
# ACPI_EXTRACT_ALL_CODE - create an array storing the generated AML bytecode
#
# ACPI_EXTRACT is not allowed anywhere else in code, except in comments.
import re;
import sys;
import fileinput;
aml = []
asl = []
output = {}
debug = ""
class asl_line:
line = None
lineno = None
aml_offset = None
def die(diag):
sys.stderr.write("Error: %s; %s\n" % (diag, debug))
sys.exit(1)
#Store an ASL command, matching AML offset, and input line (for debugging)
def add_asl(lineno, line):
l = asl_line()
l.line = line
l.lineno = lineno
l.aml_offset = len(aml)
asl.append(l)
#Store an AML byte sequence
#Verify that offset output by iasl matches # of bytes so far
def add_aml(offset, line):
o = int(offset, 16);
# Sanity check: offset must match size of code so far
if (o != len(aml)):
die("Offset 0x%x != 0x%x" % (o, len(aml)))
# Strip any trailing dots and ASCII dump after "
line = re.sub(r'\s*\.*\s*".*$',"", line)
# Strip traling whitespace
line = re.sub(r'\s+$',"", line)
# Strip leading whitespace
line = re.sub(r'^\s+',"", line)
# Split on whitespace
code = re.split(r'\s+', line)
for c in code:
# Require a legal hex number, two digits
if (not(re.search(r'^[0-9A-Fa-f][0-9A-Fa-f]$', c))):
die("Unexpected octet %s" % c);
aml.append(int(c, 16));
# Process aml bytecode array, decoding AML
def aml_pkglen_bytes(offset):
# PkgLength can be multibyte. Bits 8-7 give the # of extra bytes.
pkglenbytes = aml[offset] >> 6;
return pkglenbytes + 1
def aml_pkglen(offset):
pkgstart = offset
pkglenbytes = aml_pkglen_bytes(offset)
pkglen = aml[offset] & 0x3F
# If multibyte, first nibble only uses bits 0-3
if ((pkglenbytes > 1) and (pkglen & 0x30)):
die("PkgLen bytes 0x%x but first nibble 0x%x expected 0x0X" %
(pkglen, pkglen))
offset += 1
pkglenbytes -= 1
for i in range(pkglenbytes):
pkglen |= aml[offset + i] << (i * 8 + 4)
if (len(aml) < pkgstart + pkglen):
die("PckgLen 0x%x at offset 0x%x exceeds AML size 0x%x" %
(pkglen, offset, len(aml)))
return pkglen
# Given method offset, find its NameString offset
def aml_method_string(offset):
#0x14 MethodOp PkgLength NameString MethodFlags TermList
if (aml[offset] != 0x14):
die( "Method offset 0x%x: expected 0x14 actual 0x%x" %
(offset, aml[offset]));
offset += 1;
pkglenbytes = aml_pkglen_bytes(offset)
offset += pkglenbytes;
return offset;
# Given name offset, find its NameString offset
def aml_name_string(offset):
#0x08 NameOp NameString DataRef
if (aml[offset] != 0x08):
die( "Name offset 0x%x: expected 0x08 actual 0x%x" %
(offset, aml[offset]));
offset += 1
# Block Name Modifier. Skip it.
if (aml[offset] == 0x5c or aml[offset] == 0x5e):
offset += 1
return offset;
# Given data offset, find 8 byte buffer offset
def aml_data_buffer8(offset):
#0x08 NameOp NameString DataRef
expect = [0x11, 0x0B, 0x0A, 0x08]
if (aml[offset:offset+4] != expect):
die( "Name offset 0x%x: expected %s actual %s" %
(offset, aml[offset:offset+4], expect))
return offset + len(expect)
# Given data offset, find dword const offset
def aml_data_dword_const(offset):
#0x08 NameOp NameString DataRef
if (aml[offset] != 0x0C):
die( "Name offset 0x%x: expected 0x0C actual 0x%x" %
(offset, aml[offset]));
return offset + 1;
# Given data offset, find word const offset
def aml_data_word_const(offset):
#0x08 NameOp NameString DataRef
if (aml[offset] != 0x0B):
die( "Name offset 0x%x: expected 0x0B actual 0x%x" %
(offset, aml[offset]));
return offset + 1;
# Given data offset, find byte const offset
def aml_data_byte_const(offset):
#0x08 NameOp NameString DataRef
if (aml[offset] != 0x0A):
die( "Name offset 0x%x: expected 0x0A actual 0x%x" %
(offset, aml[offset]));
return offset + 1;
# Find name'd buffer8
def aml_name_buffer8(offset):
return aml_data_buffer8(aml_name_string(offset) + 4)
# Given name offset, find dword const offset
def aml_name_dword_const(offset):
return aml_data_dword_const(aml_name_string(offset) + 4)
# Given name offset, find word const offset
def aml_name_word_const(offset):
return aml_data_word_const(aml_name_string(offset) + 4)
# Given name offset, find byte const offset
def aml_name_byte_const(offset):
return aml_data_byte_const(aml_name_string(offset) + 4)
def aml_device_start(offset):
#0x5B 0x82 DeviceOp PkgLength NameString
if ((aml[offset] != 0x5B) or (aml[offset + 1] != 0x82)):
die( "Name offset 0x%x: expected 0x5B 0x82 actual 0x%x 0x%x" %
(offset, aml[offset], aml[offset + 1]));
return offset
def aml_device_string(offset):
#0x5B 0x82 DeviceOp PkgLength NameString
start = aml_device_start(offset)
offset += 2
pkglenbytes = aml_pkglen_bytes(offset)
offset += pkglenbytes
return offset
def aml_device_end(offset):
start = aml_device_start(offset)
offset += 2
pkglenbytes = aml_pkglen_bytes(offset)
pkglen = aml_pkglen(offset)
return offset + pkglen
def aml_processor_start(offset):
#0x5B 0x83 ProcessorOp PkgLength NameString ProcID
if ((aml[offset] != 0x5B) or (aml[offset + 1] != 0x83)):
die( "Name offset 0x%x: expected 0x5B 0x83 actual 0x%x 0x%x" %
(offset, aml[offset], aml[offset + 1]));
return offset
def aml_processor_string(offset):
#0x5B 0x83 ProcessorOp PkgLength NameString ProcID
start = aml_processor_start(offset)
offset += 2
pkglenbytes = aml_pkglen_bytes(offset)
offset += pkglenbytes
return offset
def aml_processor_end(offset):
start = aml_processor_start(offset)
offset += 2
pkglenbytes = aml_pkglen_bytes(offset)
pkglen = aml_pkglen(offset)
return offset + pkglen
def aml_package_start(offset):
offset = aml_name_string(offset) + 4
# 0x12 PkgLength NumElements PackageElementList
if (aml[offset] != 0x12):
die( "Name offset 0x%x: expected 0x12 actual 0x%x" %
(offset, aml[offset]));
offset += 1
return offset + aml_pkglen_bytes(offset) + 1
lineno = 0
for line in fileinput.input():
# Strip trailing newline
line = line.rstrip();
# line number and debug string to output in case of errors
lineno = lineno + 1
debug = "input line %d: %s" % (lineno, line)
#ASL listing: space, then line#, then ...., then code
pasl = re.compile('^\s+([0-9]+)(:\s\s|\.\.\.\.)\s*')
m = pasl.search(line)
if (m):
add_asl(lineno, pasl.sub("", line));
# AML listing: offset in hex, then ...., then code
paml = re.compile('^([0-9A-Fa-f]+)(:\s\s|\.\.\.\.)\s*')
m = paml.search(line)
if (m):
add_aml(m.group(1), paml.sub("", line))
# Now go over code
# Track AML offset of a previous non-empty ASL command
prev_aml_offset = -1
for i in range(len(asl)):
debug = "input line %d: %s" % (asl[i].lineno, asl[i].line)
l = asl[i].line
# skip if not an extract directive
a = len(re.findall(r'ACPI_EXTRACT', l))
if (not a):
# If not empty, store AML offset. Will be used for sanity checks
# IASL seems to put {}. at random places in the listing.
# Ignore any non-words for the purpose of this test.
m = re.search(r'\w+', l)
if (m):
prev_aml_offset = asl[i].aml_offset
continue
if (a > 1):
die("Expected at most one ACPI_EXTRACT per line, actual %d" % a)
mext = re.search(r'''
^\s* # leading whitespace
/\*\s* # start C comment
(ACPI_EXTRACT_\w+) # directive: group(1)
\s+ # whitspace separates directive from array name
(\w+) # array name: group(2)
\s*\*/ # end of C comment
\s*$ # trailing whitespace
''', l, re.VERBOSE)
if (not mext):
die("Stray ACPI_EXTRACT in input")
# previous command must have produced some AML,
# otherwise we are in a middle of a block
if (prev_aml_offset == asl[i].aml_offset):
die("ACPI_EXTRACT directive in the middle of a block")
directive = mext.group(1)
array = mext.group(2)
offset = asl[i].aml_offset
if (directive == "ACPI_EXTRACT_ALL_CODE"):
if array in output:
die("%s directive used more than once" % directive)
output[array] = aml
continue
if (directive == "ACPI_EXTRACT_NAME_BUFFER8"):
offset = aml_name_buffer8(offset)
elif (directive == "ACPI_EXTRACT_NAME_DWORD_CONST"):
offset = aml_name_dword_const(offset)
elif (directive == "ACPI_EXTRACT_NAME_WORD_CONST"):
offset = aml_name_word_const(offset)
elif (directive == "ACPI_EXTRACT_NAME_BYTE_CONST"):
offset = aml_name_byte_const(offset)
elif (directive == "ACPI_EXTRACT_NAME_STRING"):
offset = aml_name_string(offset)
elif (directive == "ACPI_EXTRACT_METHOD_STRING"):
offset = aml_method_string(offset)
elif (directive == "ACPI_EXTRACT_DEVICE_START"):
offset = aml_device_start(offset)
elif (directive == "ACPI_EXTRACT_DEVICE_STRING"):
offset = aml_device_string(offset)
elif (directive == "ACPI_EXTRACT_DEVICE_END"):
offset = aml_device_end(offset)
elif (directive == "ACPI_EXTRACT_PROCESSOR_START"):
offset = aml_processor_start(offset)
elif (directive == "ACPI_EXTRACT_PROCESSOR_STRING"):
offset = aml_processor_string(offset)
elif (directive == "ACPI_EXTRACT_PROCESSOR_END"):
offset = aml_processor_end(offset)
elif (directive == "ACPI_EXTRACT_PKG_START"):
offset = aml_package_start(offset)
else:
die("Unsupported directive %s" % directive)
if array not in output:
output[array] = []
output[array].append(offset)
debug = "at end of file"
def get_value_type(maxvalue):
#Use type large enough to fit the table
if (maxvalue >= 0x10000):
return "int"
elif (maxvalue >= 0x100):
return "short"
else:
return "char"
# Pretty print output
for array in output.keys():
otype = get_value_type(max(output[array]))
odata = []
for value in output[array]:
odata.append("0x%x" % value)
sys.stdout.write("static unsigned %s %s[] = {\n" % (otype, array))
sys.stdout.write(",\n".join(odata))
sys.stdout.write('\n};\n');

View File

@ -0,0 +1,51 @@
#!/usr/bin/python
# Copyright (C) 2011 Red Hat, Inc., Michael S. Tsirkin <mst@redhat.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, see <http://www.gnu.org/licenses/>.
# Read a preprocessed ASL listing and put each ACPI_EXTRACT
# directive in a comment, to make iasl skip it.
# We also put each directive on a new line, the machinery
# in tools/acpi_extract.py requires this.
import re;
import sys;
import fileinput;
def die(diag):
sys.stderr.write("Error: %s\n" % (diag))
sys.exit(1)
# Note: () around pattern make split return matched string as part of list
psplit = re.compile(r''' (
\b # At word boundary
ACPI_EXTRACT_\w+ # directive
\s+ # some whitespace
\w+ # array name
)''', re.VERBOSE);
lineno = 0
for line in fileinput.input():
# line number and debug string to output in case of errors
lineno = lineno + 1
debug = "input line %d: %s" % (lineno, line.rstrip())
s = psplit.split(line);
# The way split works, each odd item is the matching ACPI_EXTRACT directive.
# Put each in a comment, and on a line by itself.
for i in range(len(s)):
if (i % 2):
sys.stdout.write("\n/* %s */\n" % s[i])
else:
sys.stdout.write(s[i])

4
scripts/update-acpi.sh Normal file
View File

@ -0,0 +1,4 @@
cd x86_64-softmmu
for file in hw/i386/*.hex; do
cp -f $file ../$file.generated
done

3
vl.c
View File

@ -4336,6 +4336,9 @@ int main(int argc, char **argv, char **envp)
qemu_register_reset(qbus_reset_all_fn, sysbus_get_default());
qemu_run_machine_init_done_notifiers();
/* Done notifiers can load ROMs */
rom_load_done();
qemu_system_reset(VMRESET_SILENT);
if (loadvm) {
if (load_vmstate(loadvm) < 0) {