All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff.
@ 2009-09-30 10:17 Isaku Yamahata
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 01/61] acpi: split out pc smbus routines from acpi.c into pc_smbus.c Isaku Yamahata
                   ` (64 more replies)
  0 siblings, 65 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:17 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

This patch set is for Q35 chipset(GMCH and ICH9) based PC.

Anthony,
I'm aware that this patch set is already conflicting to other's patches.
Which tree/changeset do you want me to rebase?
Your staging qemu repo doesn't seem to include the latest patches.
As I'm seeing regular patch conflicts, I need your help as a maintainer.

The motivation is to support newer hardware features because
piix chipset is very old.
Especially I have PCI express in mind and this is the basic
infrastructure for PCI express hot plug and PCI express native 
direct attach.
With this patch set, you can see PCIe MMCONFIG space and 3+ PCI busses.
I haven't implemented PCI express port/switch and PCI express hot plug.
This is my next TODO. and then PCI express native direct attach/passthrough

I can boot Linux 2.6.30 with PCIe MMCONFIG with APIC mode pci interrupt
routing. I haven't tested other OSes.
(I patches linux kernel to test MMCONFIG because Linux uses conventional
IO port to PCI config space, i.e. 256)
To use this patch, bios also needs patches I'll sent out soon.


Firstly this patch set splits up current piix pc code into
piix specific code and common code.
Those patches are almost same as the one I sent out before.
And then PCI related patches comes in. They cleans up PCI related code
, implements PCIe MMCONFIG and fixes PCI bridge.
Thirdly q35 chipset is implemented.
Lastly IO apic related 

Changes from split out piix specific part from pc emulator. V6
- rebased to 731c54f86988d3f28268f184fabfe9b2a32fb5d3
- PCIe MMCONFIG
- pci bridge related fixes
- chipset emulator works.
- IOAPIC patches

Changes from v5:
- rebased 0.11.0-rc0
- changed qemu_system_powerdown_register() to call
  qemu_system_shutdown_request() if qemu_system_shutdown() is called before
  registering.

Changes from v4:
- fix version number.
- rebased anthony's staging tree whose latest change set is
  62969268f876c547ee64da6d60e0f363e0f1df75

Changes from v3:
- move qemu_system_powerdown() in vl.c and more generic
  following the comment by Marcelo Tosatti <mtosatti@redhat.com>
  acpi.c: make qemu_system_powerdown() piix independent.
- define cmos_set_s3_resume_init() and cmos_set_s3_resume() in pc.c
  even if TARGET_I386 isn't defined following th ecommit by
  Paolo Bonzini <bonzini@gnu.org>
  pc.c: remove a global variable, RTCState *rtc_state.
- minor compilation fixes

Changes from v2:
- clean up pc_pci_device_init() not to use unnecessary braces.

Changes from v1:
- make patches full bisectable
- typo s/allocte/allocate/
- some minor fixes
- dropped a merged patch


Isaku Yamahata (61):
  acpi: split out pc smbus routines from acpi.c into pc_smbus.c
  acpi: split out apm register emulation from acpi.c
  acpi: add acpi constants from linux header files and use them.
  acpi: split acpi.c into the common part and the piix4 part.
  acpi_piix4: remove unused variable in get_pmsts().
  pc: fix file stream leak in multiboot loader.
  pc, i440fx: Make smm enable/disable function i440fx independent.
  pc: make an unnecessary global variable, pit, local.
  pc: remove a global variable, floppy_controller.
  pc: remove a global variable, RTCState *rtc_state.
  pc: introduce a function to allocate cpu irq.
  pc: make pc_init1() not refer ferr_irq directly.
  pc: split out cpu initialization from pc_init1() into pc_cpus_init().
  pc: split out memory allocation from pc_init1() into pc_memory_init()
  pc: split out vga initialization from pc_init1() into pc_vga_init().
  pc: split out basic device init from pc_init1() into
    pc_basic_device_init()
  pc: split out pci device init from pc_init1() into
    pc_pci_device_init()
  pc: split out piix specific part from pc.c into pc_piix.c
  pc_piix: initialize ioapic before use.
  pci: fix PCI_DPRINTF() wrt variadic macro.
  pci: introduce constant PCI_NUM_PINS for the number of interrupt
    pins, 4.
  pci: use appropriate PRIs in PCI_DPRINTF().
  pci: use PCI_SLOT() and PCI_FUNC().
  pci: define a constant to represent a unmapped bar and use it.
  pci: use uint64_t for bar addr and size instead of uint32_t.
  pci: 64bit bar support.
  pci: clean up of pci_update_mappings()
  pci: factor out while(bus) bus->next loop logic into
    pci_find_bus_from().
  pci: factor out the logic to get pci device from address.
  pci_host.h: split non-inline static function in pci_host.h into
    pci_host_c.h
  pci: pcie host and mmcfg support.
  pci: helper functions to access PCIDevice::config
  pci: use the symbolic constant, PCI_ROM_ADDRESS_ENABLE instead of 1.
  pci: introduce pci_swizzle_map_irq_fn() for interrupt pin swizzle.
  piix_pci: use pci_swizzle_map_irq_fn().
  pci: use QLIST_ macro instead of direct list manipulation.
  pci: add helper function for pci config write function to check
    address.
  pci: fix pci_default_write_config()
  pci: factor out config update logic.
  pci: use qdev to get parent bus with PCIBus.
  pci: make bar update function aware of pci bridge.
  pci/brdige: qdevfy and initialize secondary bus and subordinate bus.
  pci: add helper function to initialize wmask.
  pci: initialize wmask according to pci header type.
  pci/monitor: print out bridge's filtering values and so on.
  pci/bridge: implement intel 82801ba bridge.
  pci.h: add more status constats.
  pci id: add subclass codes for serial device.
  pci hot add: pass opaque argument to callback.
  pci hotadd, acpi_piix4: remove global variables.
  vmstate: add a macro for pointer to struct, VMSTATE_STRUCT_POINTER.
  pci: add a hook to replace default pci bus instead of 0 bus.
  pc q35 based chipset emulator
  pci: add opaque argument to pci_map_irq_fn().
  ioapic: make ioapic_set_irq() static.
  ioapic: clean up of  #ifdef DEBUG_IOAPIC.
  ioapic: add callback when entry is set or ioapic is reset
  ioapic: make the number of pins configurable.
  ioapic: make irr accept more than 32 pins.
  pci: add opaque arg to pci_map_irq_fn.
  pc_q35: apic mode for pci interrupt routing.

 Makefile.target                 |    5 +-
 hw/ac97.c                       |    2 +-
 hw/acpi.c                       |  736 +--------------------------
 hw/acpi.h                       |   78 +++
 hw/acpi_ich9.c                  |  565 ++++++++++++++++++++
 hw/acpi_ich9.h                  |   57 ++
 hw/acpi_piix4.c                 |  582 +++++++++++++++++++++
 hw/apb_pci.c                    |   16 +-
 hw/cirrus_vga.c                 |    8 +-
 hw/e1000.c                      |   12 +-
 hw/eepro100.c                   |   10 +-
 hw/es1370.c                     |    2 +-
 hw/grackle_pci.c                |    4 +-
 hw/gt64xxx.c                    |    4 +-
 hw/hw.h                         |   42 ++
 hw/ide/pci.c                    |    4 +-
 hw/ioapic.c                     |  137 ++++--
 hw/lsi53c895a.c                 |    6 +-
 hw/macio.c                      |    2 +-
 hw/msix.c                       |    2 +-
 hw/msix.h                       |    2 +-
 hw/ne2000.c                     |    2 +-
 hw/openpic.c                    |    2 +-
 hw/pc.c                         |  344 ++++---------
 hw/pc.h                         |   48 ++-
 hw/pc_apm.c                     |   89 ++++
 hw/pc_apm.h                     |   43 ++
 hw/pc_piix.c                    |  241 +++++++++
 hw/pc_q35.c                     |  220 ++++++++
 hw/pc_smbus.c                   |  178 +++++++
 hw/pc_smbus.h                   |   43 ++
 hw/pci-hotplug.c                |    7 +-
 hw/pci.c                        | 1102 +++++++++++++++++++++++++++++++--------
 hw/pci.h                        |  261 +++++++++-
 hw/pci_bridge.c                 |   63 +++
 hw/pci_bridge.h                 |   38 ++
 hw/pci_host.h                   |  110 +---
 hw/{pci_host.h => pci_host_c.h} |    8 +-
 hw/pci_ids.h                    |   28 +
 hw/pcnet.c                      |    9 +-
 hw/piix_pci.c                   |   14 +-
 hw/ppc4xx_pci.c                 |    4 +-
 hw/ppce500_pci.c                |    4 +-
 hw/prep_pci.c                   |    4 +-
 hw/q35.c                        |  784 ++++++++++++++++++++++++++++
 hw/q35.h                        |  232 ++++++++
 hw/q35_smbus.c                  |  150 ++++++
 hw/r2d.c                        |    2 +-
 hw/rtl8139.c                    |    4 +-
 hw/sun4u.c                      |    2 +-
 hw/unin_pci.c                   |    4 +-
 hw/usb-ohci.c                   |    2 +-
 hw/usb-uhci.c                   |    2 +-
 hw/versatile_pci.c              |    2 +-
 hw/vga-pci.c                    |    2 +-
 hw/virtio-pci.c                 |    2 +-
 hw/vmware_vga.c                 |    4 +-
 hw/wdt_i6300esb.c               |    5 +-
 sysemu.h                        |    4 +-
 59 files changed, 4932 insertions(+), 1407 deletions(-)
 create mode 100644 hw/acpi.h
 create mode 100644 hw/acpi_ich9.c
 create mode 100644 hw/acpi_ich9.h
 create mode 100644 hw/acpi_piix4.c
 create mode 100644 hw/pc_apm.c
 create mode 100644 hw/pc_apm.h
 create mode 100644 hw/pc_piix.c
 create mode 100644 hw/pc_q35.c
 create mode 100644 hw/pc_smbus.c
 create mode 100644 hw/pc_smbus.h
 create mode 100644 hw/pci_bridge.c
 create mode 100644 hw/pci_bridge.h
 copy hw/{pci_host.h => pci_host_c.h} (96%)
 create mode 100644 hw/q35.c
 create mode 100644 hw/q35.h
 create mode 100644 hw/q35_smbus.c

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 01/61] acpi: split out pc smbus routines from acpi.c into pc_smbus.c
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
@ 2009-09-30 10:17 ` Isaku Yamahata
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 02/61] acpi: split out apm register emulation from acpi.c Isaku Yamahata
                   ` (63 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:17 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

Split out pc smbus routines from acpi.c into pc_smbus.c and
use it.
The split out smbus emulation will be used later.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 Makefile.target |    2 +
 hw/acpi.c       |  164 +++------------------------------------------------
 hw/pc_smbus.c   |  178 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/pc_smbus.h   |   43 +++++++++++++
 4 files changed, 231 insertions(+), 156 deletions(-)
 create mode 100644 hw/pc_smbus.c
 create mode 100644 hw/pc_smbus.h

diff --git a/Makefile.target b/Makefile.target
index 1f4518c..9b87213 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -187,6 +187,7 @@ obj-i386-y += cirrus_vga.o apic.o ioapic.o parallel.o acpi.o piix_pci.o
 obj-i386-y += usb-uhci.o vmmouse.o vmport.o vmware_vga.o hpet.o
 obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
 obj-i386-y += ne2000-isa.o
+obj-i386-y += pc_smbus.o
 
 # shared objects
 obj-ppc-y = ppc.o ide/core.o ide/qdev.o ide/isa.o ide/pci.o ide/macio.o
@@ -216,6 +217,7 @@ obj-mips-y += ide/core.o ide/qdev.o ide/isa.o ide/pci.o
 obj-mips-y += gt64xxx.o pckbd.o fdc.o mc146818rtc.o usb-uhci.o acpi.o ds1225y.o
 obj-mips-y += piix4.o parallel.o cirrus_vga.o pcspk.o $(sound-obj-y)
 obj-mips-y += mipsnet.o ne2000-isa.o
+obj-mips-y += pc_smbus.o
 obj-mips-y += pflash_cfi01.o
 obj-mips-y += vmware_vga.o
 
diff --git a/hw/acpi.c b/hw/acpi.c
index b14b9f4..5d8aa73 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -17,6 +17,7 @@
  */
 #include "hw.h"
 #include "pc.h"
+#include "pc_smbus.h"
 #include "pci.h"
 #include "qemu-timer.h"
 #include "sysemu.h"
@@ -40,15 +41,9 @@ typedef struct PIIX4PMState {
     uint8_t apms;
     QEMUTimer *tmr_timer;
     int64_t tmr_overflow_time;
-    i2c_bus *smbus;
-    uint8_t smb_stat;
-    uint8_t smb_ctl;
-    uint8_t smb_cmd;
-    uint8_t smb_addr;
-    uint8_t smb_data0;
-    uint8_t smb_data1;
-    uint8_t smb_data[32];
-    uint8_t smb_index;
+
+    PCSMBus smb;
+
     qemu_irq irq;
 } PIIX4PMState;
 
@@ -66,14 +61,6 @@ typedef struct PIIX4PMState {
 #define ACPI_ENABLE 0xf1
 #define ACPI_DISABLE 0xf0
 
-#define SMBHSTSTS 0x00
-#define SMBHSTCNT 0x02
-#define SMBHSTCMD 0x03
-#define SMBHSTADD 0x04
-#define SMBHSTDAT0 0x05
-#define SMBHSTDAT1 0x06
-#define SMBBLKDAT 0x07
-
 static PIIX4PMState *pm_state;
 
 static uint32_t get_pmtmr(PIIX4PMState *s)
@@ -279,141 +266,6 @@ static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val)
 #endif
 }
 
-static void smb_transaction(PIIX4PMState *s)
-{
-    uint8_t prot = (s->smb_ctl >> 2) & 0x07;
-    uint8_t read = s->smb_addr & 0x01;
-    uint8_t cmd = s->smb_cmd;
-    uint8_t addr = s->smb_addr >> 1;
-    i2c_bus *bus = s->smbus;
-
-#ifdef DEBUG
-    printf("SMBus trans addr=0x%02x prot=0x%02x\n", addr, prot);
-#endif
-    switch(prot) {
-    case 0x0:
-        smbus_quick_command(bus, addr, read);
-        break;
-    case 0x1:
-        if (read) {
-            s->smb_data0 = smbus_receive_byte(bus, addr);
-        } else {
-            smbus_send_byte(bus, addr, cmd);
-        }
-        break;
-    case 0x2:
-        if (read) {
-            s->smb_data0 = smbus_read_byte(bus, addr, cmd);
-        } else {
-            smbus_write_byte(bus, addr, cmd, s->smb_data0);
-        }
-        break;
-    case 0x3:
-        if (read) {
-            uint16_t val;
-            val = smbus_read_word(bus, addr, cmd);
-            s->smb_data0 = val;
-            s->smb_data1 = val >> 8;
-        } else {
-            smbus_write_word(bus, addr, cmd, (s->smb_data1 << 8) | s->smb_data0);
-        }
-        break;
-    case 0x5:
-        if (read) {
-            s->smb_data0 = smbus_read_block(bus, addr, cmd, s->smb_data);
-        } else {
-            smbus_write_block(bus, addr, cmd, s->smb_data, s->smb_data0);
-        }
-        break;
-    default:
-        goto error;
-    }
-    return;
-
-  error:
-    s->smb_stat |= 0x04;
-}
-
-static void smb_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
-{
-    PIIX4PMState *s = opaque;
-    addr &= 0x3f;
-#ifdef DEBUG
-    printf("SMB writeb port=0x%04x val=0x%02x\n", addr, val);
-#endif
-    switch(addr) {
-    case SMBHSTSTS:
-        s->smb_stat = 0;
-        s->smb_index = 0;
-        break;
-    case SMBHSTCNT:
-        s->smb_ctl = val;
-        if (val & 0x40)
-            smb_transaction(s);
-        break;
-    case SMBHSTCMD:
-        s->smb_cmd = val;
-        break;
-    case SMBHSTADD:
-        s->smb_addr = val;
-        break;
-    case SMBHSTDAT0:
-        s->smb_data0 = val;
-        break;
-    case SMBHSTDAT1:
-        s->smb_data1 = val;
-        break;
-    case SMBBLKDAT:
-        s->smb_data[s->smb_index++] = val;
-        if (s->smb_index > 31)
-            s->smb_index = 0;
-        break;
-    default:
-        break;
-    }
-}
-
-static uint32_t smb_ioport_readb(void *opaque, uint32_t addr)
-{
-    PIIX4PMState *s = opaque;
-    uint32_t val;
-
-    addr &= 0x3f;
-    switch(addr) {
-    case SMBHSTSTS:
-        val = s->smb_stat;
-        break;
-    case SMBHSTCNT:
-        s->smb_index = 0;
-        val = s->smb_ctl & 0x1f;
-        break;
-    case SMBHSTCMD:
-        val = s->smb_cmd;
-        break;
-    case SMBHSTADD:
-        val = s->smb_addr;
-        break;
-    case SMBHSTDAT0:
-        val = s->smb_data0;
-        break;
-    case SMBHSTDAT1:
-        val = s->smb_data1;
-        break;
-    case SMBBLKDAT:
-        val = s->smb_data[s->smb_index++];
-        if (s->smb_index > 31)
-            s->smb_index = 0;
-        break;
-    default:
-        val = 0;
-        break;
-    }
-#ifdef DEBUG
-    printf("SMB readb port=0x%04x val=0x%02x\n", addr, val);
-#endif
-    return val;
-}
-
 static void pm_io_space_update(PIIX4PMState *s)
 {
     uint32_t pm_io_base;
@@ -542,8 +394,8 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
     pci_conf[0x90] = smb_io_base | 1;
     pci_conf[0x91] = smb_io_base >> 8;
     pci_conf[0xd2] = 0x09;
-    register_ioport_write(smb_io_base, 64, 1, smb_ioport_writeb, s);
-    register_ioport_read(smb_io_base, 64, 1, smb_ioport_readb, s);
+    register_ioport_write(smb_io_base, 64, 1, smb_ioport_writeb, &s->smb);
+    register_ioport_read(smb_io_base, 64, 1, smb_ioport_readb, &s->smb);
 
     s->tmr_timer = qemu_new_timer(vm_clock, pm_tmr_timer, s);
 
@@ -551,11 +403,11 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
 
     vmstate_register(0, &vmstate_acpi, s);
 
-    s->smbus = i2c_init_bus(NULL, "i2c");
+    pc_smbus_init(&s->smb);
     s->irq = sci_irq;
     qemu_register_reset(piix4_reset, s);
 
-    return s->smbus;
+    return s->smb.smbus;
 }
 
 #define GPE_BASE 0xafe0
diff --git a/hw/pc_smbus.c b/hw/pc_smbus.c
new file mode 100644
index 0000000..850260d
--- /dev/null
+++ b/hw/pc_smbus.c
@@ -0,0 +1,178 @@
+/*
+ * PC SMBus implementation
+ * splitted from acpi.c
+ *
+ * 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 Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+#include "hw.h"
+#include "pc.h"
+#include "pc_smbus.h"
+#include "pci.h"
+#include "qemu-timer.h"
+#include "sysemu.h"
+#include "i2c.h"
+#include "smbus.h"
+#include "kvm.h"
+
+/* no save/load? */
+
+#define SMBHSTSTS       0x00
+#define SMBHSTCNT       0x02
+#define SMBHSTCMD       0x03
+#define SMBHSTADD       0x04
+#define SMBHSTDAT0      0x05
+#define SMBHSTDAT1      0x06
+#define SMBBLKDAT       0x07
+
+static void smb_transaction(PCSMBus *s)
+{
+    uint8_t prot = (s->smb_ctl >> 2) & 0x07;
+    uint8_t read = s->smb_addr & 0x01;
+    uint8_t cmd = s->smb_cmd;
+    uint8_t addr = s->smb_addr >> 1;
+    i2c_bus *bus = s->smbus;
+
+#ifdef DEBUG
+    printf("SMBus trans addr=0x%02x prot=0x%02x\n", addr, prot);
+#endif
+    switch(prot) {
+    case 0x0:
+        smbus_quick_command(bus, addr, read);
+        break;
+    case 0x1:
+        if (read) {
+            s->smb_data0 = smbus_receive_byte(bus, addr);
+        } else {
+            smbus_send_byte(bus, addr, cmd);
+        }
+        break;
+    case 0x2:
+        if (read) {
+            s->smb_data0 = smbus_read_byte(bus, addr, cmd);
+        } else {
+            smbus_write_byte(bus, addr, cmd, s->smb_data0);
+        }
+        break;
+    case 0x3:
+        if (read) {
+            uint16_t val;
+            val = smbus_read_word(bus, addr, cmd);
+            s->smb_data0 = val;
+            s->smb_data1 = val >> 8;
+        } else {
+            smbus_write_word(bus, addr, cmd, (s->smb_data1 << 8) | s->smb_data0);
+        }
+        break;
+    case 0x5:
+        if (read) {
+            s->smb_data0 = smbus_read_block(bus, addr, cmd, s->smb_data);
+        } else {
+            smbus_write_block(bus, addr, cmd, s->smb_data, s->smb_data0);
+        }
+        break;
+    default:
+        goto error;
+    }
+    return;
+
+  error:
+    s->smb_stat |= 0x04;
+}
+
+void smb_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+    PCSMBus *s = opaque;
+    addr &= 0x3f;
+#ifdef DEBUG
+    printf("SMB writeb port=0x%04x val=0x%02x\n", addr, val);
+#endif
+    switch(addr) {
+    case SMBHSTSTS:
+        s->smb_stat = 0;
+        s->smb_index = 0;
+        break;
+    case SMBHSTCNT:
+        s->smb_ctl = val;
+        if (val & 0x40)
+            smb_transaction(s);
+        break;
+    case SMBHSTCMD:
+        s->smb_cmd = val;
+        break;
+    case SMBHSTADD:
+        s->smb_addr = val;
+        break;
+    case SMBHSTDAT0:
+        s->smb_data0 = val;
+        break;
+    case SMBHSTDAT1:
+        s->smb_data1 = val;
+        break;
+    case SMBBLKDAT:
+        s->smb_data[s->smb_index++] = val;
+        if (s->smb_index > 31)
+            s->smb_index = 0;
+        break;
+    default:
+        break;
+    }
+}
+
+uint32_t smb_ioport_readb(void *opaque, uint32_t addr)
+{
+    PCSMBus *s = opaque;
+    uint32_t val;
+
+    addr &= 0x3f;
+    switch(addr) {
+    case SMBHSTSTS:
+        val = s->smb_stat;
+        break;
+    case SMBHSTCNT:
+        s->smb_index = 0;
+        val = s->smb_ctl & 0x1f;
+        break;
+    case SMBHSTCMD:
+        val = s->smb_cmd;
+        break;
+    case SMBHSTADD:
+        val = s->smb_addr;
+        break;
+    case SMBHSTDAT0:
+        val = s->smb_data0;
+        break;
+    case SMBHSTDAT1:
+        val = s->smb_data1;
+        break;
+    case SMBBLKDAT:
+        val = s->smb_data[s->smb_index++];
+        if (s->smb_index > 31)
+            s->smb_index = 0;
+        break;
+    default:
+        val = 0;
+        break;
+    }
+#ifdef DEBUG
+    printf("SMB readb port=0x%04x val=0x%02x\n", addr, val);
+#endif
+    return val;
+}
+
+void pc_smbus_init(PCSMBus *smb)
+{
+    smb->smbus = i2c_init_bus(NULL, "i2c");
+}
diff --git a/hw/pc_smbus.h b/hw/pc_smbus.h
new file mode 100644
index 0000000..5e5a66f
--- /dev/null
+++ b/hw/pc_smbus.h
@@ -0,0 +1,43 @@
+/*
+ * QEMU PC SMBUS controller Emulation
+ *
+ *  Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ *                     VA Linux Systems Japan K.K.
+ *
+ *  This is based on piix_pci.c, but heavily modified.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * 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 Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+#ifndef PC_SMBUS_H
+#define PC_SMBUS_H
+
+typedef struct PCSMBus {
+    i2c_bus *smbus;
+
+    uint8_t smb_stat;
+    uint8_t smb_ctl;
+    uint8_t smb_cmd;
+    uint8_t smb_addr;
+    uint8_t smb_data0;
+    uint8_t smb_data1;
+    uint8_t smb_data[32];
+    uint8_t smb_index;
+} PCSMBus;
+
+void pc_smbus_init(PCSMBus *smb);
+void smb_ioport_writeb(void *opaque, uint32_t addr, uint32_t val);
+uint32_t smb_ioport_readb(void *opaque, uint32_t addr);
+
+#endif /* !PC_SMBUS_H */
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 02/61] acpi: split out apm register emulation from acpi.c
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 01/61] acpi: split out pc smbus routines from acpi.c into pc_smbus.c Isaku Yamahata
@ 2009-09-30 10:17 ` Isaku Yamahata
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 03/61] acpi: add acpi constants from linux header files and use them Isaku Yamahata
                   ` (62 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:17 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

Split out apm register emulation for acpi.c into pc_apm.c.
The apm emulation will be used later.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 Makefile.target |    4 +-
 hw/acpi.c       |   57 ++++++++++-------------------------
 hw/pc_apm.c     |   89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/pc_apm.h     |   43 ++++++++++++++++++++++++++
 4 files changed, 150 insertions(+), 43 deletions(-)
 create mode 100644 hw/pc_apm.c
 create mode 100644 hw/pc_apm.h

diff --git a/Makefile.target b/Makefile.target
index 9b87213..e0568b7 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -187,7 +187,7 @@ obj-i386-y += cirrus_vga.o apic.o ioapic.o parallel.o acpi.o piix_pci.o
 obj-i386-y += usb-uhci.o vmmouse.o vmport.o vmware_vga.o hpet.o
 obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
 obj-i386-y += ne2000-isa.o
-obj-i386-y += pc_smbus.o
+obj-i386-y += pc_smbus.o pc_apm.o
 
 # shared objects
 obj-ppc-y = ppc.o ide/core.o ide/qdev.o ide/isa.o ide/pci.o ide/macio.o
@@ -217,7 +217,7 @@ obj-mips-y += ide/core.o ide/qdev.o ide/isa.o ide/pci.o
 obj-mips-y += gt64xxx.o pckbd.o fdc.o mc146818rtc.o usb-uhci.o acpi.o ds1225y.o
 obj-mips-y += piix4.o parallel.o cirrus_vga.o pcspk.o $(sound-obj-y)
 obj-mips-y += mipsnet.o ne2000-isa.o
-obj-mips-y += pc_smbus.o
+obj-mips-y += pc_smbus.o pc_apm.o
 obj-mips-y += pflash_cfi01.o
 obj-mips-y += vmware_vga.o
 
diff --git a/hw/acpi.c b/hw/acpi.c
index 5d8aa73..16b69c0 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -17,6 +17,7 @@
  */
 #include "hw.h"
 #include "pc.h"
+#include "pc_apm.h"
 #include "pc_smbus.h"
 #include "pci.h"
 #include "qemu-timer.h"
@@ -37,8 +38,9 @@ typedef struct PIIX4PMState {
     uint16_t pmsts;
     uint16_t pmen;
     uint16_t pmcntrl;
-    uint8_t apmc;
-    uint8_t apms;
+
+    APMState apm;
+
     QEMUTimer *tmr_timer;
     int64_t tmr_overflow_time;
 
@@ -217,46 +219,20 @@ static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
     return val;
 }
 
-static void pm_smi_writeb(void *opaque, uint32_t addr, uint32_t val)
+static void apm_ctrl_changed(uint32_t val, void *arg)
 {
-    PIIX4PMState *s = opaque;
-    addr &= 1;
-#ifdef DEBUG
-    printf("pm_smi_writeb addr=0x%x val=0x%02x\n", addr, val);
-#endif
-    if (addr == 0) {
-        s->apmc = val;
-
-        /* ACPI specs 3.0, 4.7.2.5 */
-        if (val == ACPI_ENABLE) {
-            s->pmcntrl |= SCI_EN;
-        } else if (val == ACPI_DISABLE) {
-            s->pmcntrl &= ~SCI_EN;
-        }
+    PIIX4PMState *s = arg;
 
-        if (s->dev.config[0x5b] & (1 << 1)) {
-            cpu_interrupt(first_cpu, CPU_INTERRUPT_SMI);
-        }
-    } else {
-        s->apms = val;
+    /* ACPI specs 3.0, 4.7.2.5 */
+    if (val == ACPI_ENABLE) {
+        s->pmcntrl |= SCI_EN;
+    } else if (val == ACPI_DISABLE) {
+        s->pmcntrl &= ~SCI_EN;
     }
-}
 
-static uint32_t pm_smi_readb(void *opaque, uint32_t addr)
-{
-    PIIX4PMState *s = opaque;
-    uint32_t val;
-
-    addr &= 1;
-    if (addr == 0) {
-        val = s->apmc;
-    } else {
-        val = s->apms;
+    if (s->dev.config[0x5b] & (1 << 1)) {
+        cpu_interrupt(first_cpu, CPU_INTERRUPT_SMI);
     }
-#ifdef DEBUG
-    printf("pm_smi_readb addr=0x%x val=0x%02x\n", addr, val);
-#endif
-    return val;
 }
 
 static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val)
@@ -312,8 +288,7 @@ static const VMStateDescription vmstate_acpi = {
         VMSTATE_UINT16(pmsts, PIIX4PMState),
         VMSTATE_UINT16(pmen, PIIX4PMState),
         VMSTATE_UINT16(pmcntrl, PIIX4PMState),
-        VMSTATE_UINT8(apmc, PIIX4PMState),
-        VMSTATE_UINT8(apms, PIIX4PMState),
+        VMSTATE_STRUCT(apm, PIIX4PMState, 0, vmstate_pc_apm, APMState),
         VMSTATE_TIMER(tmr_timer, PIIX4PMState),
         VMSTATE_INT64(tmr_overflow_time, PIIX4PMState),
         VMSTATE_END_OF_LIST()
@@ -373,8 +348,8 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
 
     pci_conf[0x40] = 0x01; /* PM io base read only bit */
 
-    register_ioport_write(0xb2, 2, 1, pm_smi_writeb, s);
-    register_ioport_read(0xb2, 2, 1, pm_smi_readb, s);
+    /* APM */
+    apm_init(&s->apm, apm_ctrl_changed, s);
 
     register_ioport_write(ACPI_DBG_IO_ADDR, 4, 4, acpi_dbg_writel, s);
 
diff --git a/hw/pc_apm.c b/hw/pc_apm.c
new file mode 100644
index 0000000..730a576
--- /dev/null
+++ b/hw/pc_apm.c
@@ -0,0 +1,89 @@
+/*
+ * QEMU PC APM controller Emulation
+ *
+ *  Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ *                     VA Linux Systems Japan K.K.
+ *
+ * This is split out from acpi.c
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * 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 Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+
+#include "pc_apm.h"
+#include "hw.h"
+#include "isa.h"
+
+//#define DEBUG
+
+/* fixed I/O location */
+#define APM_CNT_IOPORT  0xb2
+#define APM_STS_IOPORT  0xb3
+
+static void apm_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+    APMState *apm = opaque;
+    addr &= 1;
+#ifdef DEBUG
+    printf("apm_ioport_writeb addr=0x%x val=0x%02x\n", addr, val);
+#endif
+    if (addr == 0) {
+        apm->apmc = val;
+
+        if (apm->callback) {
+            (apm->callback)(val, apm->arg);
+        }
+    } else {
+        apm->apms = val;
+    }
+}
+
+static uint32_t apm_ioport_readb(void *opaque, uint32_t addr)
+{
+    APMState *apm = opaque;
+    uint32_t val;
+
+    addr &= 1;
+    if (addr == 0) {
+        val = apm->apmc;
+    } else {
+        val = apm->apms;
+    }
+#ifdef DEBUG
+    printf("apm_ioport_readb addr=0x%x val=0x%02x\n", addr, val);
+#endif
+    return val;
+}
+
+const VMStateDescription vmstate_pc_apm = {
+    .name = "PC APM State",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(apmc, APMState),
+        VMSTATE_UINT8(apms, APMState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+void apm_init(APMState *apm, apm_ctrl_changed_t callback, void *arg)
+{
+    apm->callback = callback;
+    apm->arg = arg;
+
+    /* ioport 0xb2, 0xb3 */
+    register_ioport_write(APM_CNT_IOPORT, 2, 1, apm_ioport_writeb, apm);
+    register_ioport_read(APM_CNT_IOPORT, 2, 1, apm_ioport_readb, apm);
+}
diff --git a/hw/pc_apm.h b/hw/pc_apm.h
new file mode 100644
index 0000000..f7fab33
--- /dev/null
+++ b/hw/pc_apm.h
@@ -0,0 +1,43 @@
+/*
+ * QEMU PC APM controller Emulation
+ *
+ *  Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ *                     VA Linux Systems Japan K.K.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * 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 Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+
+#ifndef PC_APM_H
+#define PC_APM_H
+
+#include <stdint.h>
+#include "qemu-common.h"
+#include "hw.h"
+
+typedef void (*apm_ctrl_changed_t)(uint32_t val, void *arg);
+
+typedef struct APMState {
+    uint8_t apmc;
+    uint8_t apms;
+
+    apm_ctrl_changed_t callback;
+    void *arg;
+} APMState;
+
+void apm_init(APMState *s, apm_ctrl_changed_t callback, void *arg);
+
+extern const VMStateDescription vmstate_pc_apm;
+
+#endif /* PC_APM_H */
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 03/61] acpi: add acpi constants from linux header files and use them.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 01/61] acpi: split out pc smbus routines from acpi.c into pc_smbus.c Isaku Yamahata
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 02/61] acpi: split out apm register emulation from acpi.c Isaku Yamahata
@ 2009-09-30 10:17 ` Isaku Yamahata
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 04/61] acpi: split acpi.c into the common part and the piix4 part Isaku Yamahata
                   ` (61 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:17 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

add acpi constants from linux header files and
replace the old constants with them.
The acpi constants will be used by other file.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/acpi.c |   56 +++++++++++++++++++------------------------
 hw/acpi.h |   78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 103 insertions(+), 31 deletions(-)
 create mode 100644 hw/acpi.h

diff --git a/hw/acpi.c b/hw/acpi.c
index 16b69c0..e88a83b 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -25,12 +25,10 @@
 #include "i2c.h"
 #include "smbus.h"
 #include "kvm.h"
+#include "acpi.h"
 
 //#define DEBUG
 
-/* i82731AB (PIIX4) compatible power management function */
-#define PM_FREQ 3579545
-
 #define ACPI_DBG_IO_ADDR  0xb044
 
 typedef struct PIIX4PMState {
@@ -49,17 +47,6 @@ typedef struct PIIX4PMState {
     qemu_irq irq;
 } PIIX4PMState;
 
-#define RSM_STS (1 << 15)
-#define PWRBTN_STS (1 << 8)
-#define RTC_EN (1 << 10)
-#define PWRBTN_EN (1 << 8)
-#define GBL_EN (1 << 5)
-#define TMROF_EN (1 << 0)
-
-#define SCI_EN (1 << 0)
-
-#define SUS_EN (1 << 13)
-
 #define ACPI_ENABLE 0xf1
 #define ACPI_DISABLE 0xf0
 
@@ -68,7 +55,7 @@ static PIIX4PMState *pm_state;
 static uint32_t get_pmtmr(PIIX4PMState *s)
 {
     uint32_t d;
-    d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, get_ticks_per_sec());
+    d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY, get_ticks_per_sec());
     return d & 0xffffff;
 }
 
@@ -77,9 +64,10 @@ static int get_pmsts(PIIX4PMState *s)
     int64_t d;
     int pmsts;
     pmsts = s->pmsts;
-    d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, get_ticks_per_sec());
+    d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY,
+                 get_ticks_per_sec());
     if (d >= s->tmr_overflow_time)
-        s->pmsts |= TMROF_EN;
+        s->pmsts |= ACPI_BITMASK_TIMER_STATUS;
     return s->pmsts;
 }
 
@@ -90,11 +78,16 @@ static void pm_update_sci(PIIX4PMState *s)
 
     pmsts = get_pmsts(s);
     sci_level = (((pmsts & s->pmen) &
-                  (RTC_EN | PWRBTN_EN | GBL_EN | TMROF_EN)) != 0);
+                  (ACPI_BITMASK_RT_CLOCK_ENABLE |
+                   ACPI_BITMASK_POWER_BUTTON_ENABLE |
+                   ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
+                   ACPI_BITMASK_TIMER_ENABLE)) != 0);
     qemu_set_irq(s->irq, sci_level);
     /* schedule a timer interruption if needed */
-    if ((s->pmen & TMROF_EN) && !(pmsts & TMROF_EN)) {
-        expire_time = muldiv64(s->tmr_overflow_time, get_ticks_per_sec(), PM_FREQ);
+    if ((s->pmen & ACPI_BITMASK_TIMER_ENABLE) &&
+        !(pmsts & ACPI_BITMASK_TIMER_STATUS)) {
+        expire_time = muldiv64(s->tmr_overflow_time, get_ticks_per_sec(),
+                               PM_TIMER_FREQUENCY);
         qemu_mod_timer(s->tmr_timer, expire_time);
     } else {
         qemu_del_timer(s->tmr_timer);
@@ -117,9 +110,9 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
             int64_t d;
             int pmsts;
             pmsts = get_pmsts(s);
-            if (pmsts & val & TMROF_EN) {
+            if (pmsts & val & ACPI_BITMASK_TIMER_STATUS) {
                 /* if TMRSTS is reset, then compute the new overflow time */
-                d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ,
+                d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY,
                              get_ticks_per_sec());
                 s->tmr_overflow_time = (d + 0x800000LL) & ~0x7fffffLL;
             }
@@ -134,8 +127,8 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
     case 0x04:
         {
             int sus_typ;
-            s->pmcntrl = val & ~(SUS_EN);
-            if (val & SUS_EN) {
+            s->pmcntrl = val & ~(ACPI_BITMASK_SLEEP_ENABLE);
+            if (val & ACPI_BITMASK_SLEEP_ENABLE) {
                 /* change suspend type */
                 sus_typ = (val >> 10) & 7;
                 switch(sus_typ) {
@@ -143,9 +136,10 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
                     qemu_system_shutdown_request();
                     break;
                 case 1:
-                    /* RSM_STS should be set on resume. Pretend that resume
-                       was caused by power button */
-                    s->pmsts |= (RSM_STS | PWRBTN_STS);
+                    /* ACPI_BITMASK_WAKE_STATUS should be set on resume.
+                       Pretend that resume was caused by power button */
+                    s->pmsts |= (ACPI_BITMASK_WAKE_STATUS |
+                                 ACPI_BITMASK_POWER_BUTTON_STATUS);
                     qemu_system_reset_request();
 #if defined(TARGET_I386)
                     cmos_set_s3_resume();
@@ -225,9 +219,9 @@ static void apm_ctrl_changed(uint32_t val, void *arg)
 
     /* ACPI specs 3.0, 4.7.2.5 */
     if (val == ACPI_ENABLE) {
-        s->pmcntrl |= SCI_EN;
+        s->pmcntrl |= ACPI_BITMASK_SCI_ENABLE;
     } else if (val == ACPI_DISABLE) {
-        s->pmcntrl &= ~SCI_EN;
+        s->pmcntrl &= ~ACPI_BITMASK_SCI_ENABLE;
     }
 
     if (s->dev.config[0x5b] & (1 << 1)) {
@@ -318,8 +312,8 @@ static void piix4_powerdown(void *opaque, int irq, int power_failing)
 
     if (!s) {
         qemu_system_shutdown_request();
-    } else if (s->pmen & PWRBTN_EN) {
-        s->pmsts |= PWRBTN_EN;
+    } else if (s->pmen & ACPI_BITMASK_POWER_BUTTON_ENABLE) {
+        s->pmsts |= ACPI_BITMASK_POWER_BUTTON_STATUS;
         pm_update_sci(s);
     }
 #endif
diff --git a/hw/acpi.h b/hw/acpi.h
new file mode 100644
index 0000000..51b56b6
--- /dev/null
+++ b/hw/acpi.h
@@ -0,0 +1,78 @@
+#ifndef QEMU_HW_ACPI_H
+#define QEMU_HW_ACPI_H
+/*
+ *  Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ *                     VA Linux Systems Japan K.K.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * 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 Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+
+/* from linux include/acpi/actype.h */
+/* Default ACPI register widths */
+
+#define ACPI_GPE_REGISTER_WIDTH         8
+#define ACPI_PM1_REGISTER_WIDTH         16
+#define ACPI_PM2_REGISTER_WIDTH         8
+#define ACPI_PM_TIMER_WIDTH             32
+
+/* PM Timer ticks per second (HZ) */
+#define PM_TIMER_FREQUENCY  3579545
+
+
+/* ACPI fixed hardware registers */
+
+/* from linux/drivers/acpi/acpica/aclocal.h */
+/* Masks used to access the bit_registers */
+
+/* PM1x_STS */
+#define ACPI_BITMASK_TIMER_STATUS               0x0001
+#define ACPI_BITMASK_BUS_MASTER_STATUS          0x0010
+#define ACPI_BITMASK_GLOBAL_LOCK_STATUS         0x0020
+#define ACPI_BITMASK_POWER_BUTTON_STATUS        0x0100
+#define ACPI_BITMASK_SLEEP_BUTTON_STATUS        0x0200
+#define ACPI_BITMASK_RT_CLOCK_STATUS            0x0400
+#define ACPI_BITMASK_PCIEXP_WAKE_STATUS         0x4000	/* ACPI 3.0 */
+#define ACPI_BITMASK_WAKE_STATUS                0x8000
+
+#define ACPI_BITMASK_ALL_FIXED_STATUS           (\
+	ACPI_BITMASK_TIMER_STATUS          | \
+	ACPI_BITMASK_BUS_MASTER_STATUS     | \
+	ACPI_BITMASK_GLOBAL_LOCK_STATUS    | \
+	ACPI_BITMASK_POWER_BUTTON_STATUS   | \
+	ACPI_BITMASK_SLEEP_BUTTON_STATUS   | \
+	ACPI_BITMASK_RT_CLOCK_STATUS       | \
+	ACPI_BITMASK_WAKE_STATUS)
+
+/* PM1x_EN */
+#define ACPI_BITMASK_TIMER_ENABLE               0x0001
+#define ACPI_BITMASK_GLOBAL_LOCK_ENABLE         0x0020
+#define ACPI_BITMASK_POWER_BUTTON_ENABLE        0x0100
+#define ACPI_BITMASK_SLEEP_BUTTON_ENABLE        0x0200
+#define ACPI_BITMASK_RT_CLOCK_ENABLE            0x0400
+#define ACPI_BITMASK_PCIEXP_WAKE_DISABLE        0x4000	/* ACPI 3.0 */
+
+/* PM1x_CNT */
+#define ACPI_BITMASK_SCI_ENABLE                 0x0001
+#define ACPI_BITMASK_BUS_MASTER_RLD             0x0002
+#define ACPI_BITMASK_GLOBAL_LOCK_RELEASE        0x0004
+#define ACPI_BITMASK_SLEEP_TYPE                 0x1C00
+#define ACPI_BITMASK_SLEEP_ENABLE               0x2000
+
+/* PM2_CNT */
+#define ACPI_BITMASK_ARB_DISABLE                0x0001
+
+/* PM_TMR */
+
+#endif /* !QEMU_HW_ACPI_H */
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 04/61] acpi: split acpi.c into the common part and the piix4 part.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (2 preceding siblings ...)
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 03/61] acpi: add acpi constants from linux header files and use them Isaku Yamahata
@ 2009-09-30 10:17 ` Isaku Yamahata
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 05/61] acpi_piix4: remove unused variable in get_pmsts() Isaku Yamahata
                   ` (60 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:17 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

Split acpi.c into the common part and the piix4 specific part.
The common part will be used later.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 Makefile.target             |    4 +-
 hw/acpi.c                   |  547 -------------------------------------------
 hw/{acpi.c => acpi_piix4.c} |  191 +---------------
 3 files changed, 8 insertions(+), 734 deletions(-)
 copy hw/{acpi.c => acpi_piix4.c} (74%)

diff --git a/Makefile.target b/Makefile.target
index e0568b7..9f02ff2 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -187,7 +187,7 @@ obj-i386-y += cirrus_vga.o apic.o ioapic.o parallel.o acpi.o piix_pci.o
 obj-i386-y += usb-uhci.o vmmouse.o vmport.o vmware_vga.o hpet.o
 obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
 obj-i386-y += ne2000-isa.o
-obj-i386-y += pc_smbus.o pc_apm.o
+obj-i386-y += pc_smbus.o pc_apm.o acpi_piix4.o
 
 # shared objects
 obj-ppc-y = ppc.o ide/core.o ide/qdev.o ide/isa.o ide/pci.o ide/macio.o
@@ -217,7 +217,7 @@ obj-mips-y += ide/core.o ide/qdev.o ide/isa.o ide/pci.o
 obj-mips-y += gt64xxx.o pckbd.o fdc.o mc146818rtc.o usb-uhci.o acpi.o ds1225y.o
 obj-mips-y += piix4.o parallel.o cirrus_vga.o pcspk.o $(sound-obj-y)
 obj-mips-y += mipsnet.o ne2000-isa.o
-obj-mips-y += pc_smbus.o pc_apm.o
+obj-mips-y += pc_smbus.o pc_apm.o acpi_piix4.o
 obj-mips-y += pflash_cfi01.o
 obj-mips-y += vmware_vga.o
 
diff --git a/hw/acpi.c b/hw/acpi.c
index e88a83b..44056a1 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -17,557 +17,10 @@
  */
 #include "hw.h"
 #include "pc.h"
-#include "pc_apm.h"
-#include "pc_smbus.h"
 #include "pci.h"
-#include "qemu-timer.h"
 #include "sysemu.h"
-#include "i2c.h"
-#include "smbus.h"
-#include "kvm.h"
 #include "acpi.h"
 
-//#define DEBUG
-
-#define ACPI_DBG_IO_ADDR  0xb044
-
-typedef struct PIIX4PMState {
-    PCIDevice dev;
-    uint16_t pmsts;
-    uint16_t pmen;
-    uint16_t pmcntrl;
-
-    APMState apm;
-
-    QEMUTimer *tmr_timer;
-    int64_t tmr_overflow_time;
-
-    PCSMBus smb;
-
-    qemu_irq irq;
-} PIIX4PMState;
-
-#define ACPI_ENABLE 0xf1
-#define ACPI_DISABLE 0xf0
-
-static PIIX4PMState *pm_state;
-
-static uint32_t get_pmtmr(PIIX4PMState *s)
-{
-    uint32_t d;
-    d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY, get_ticks_per_sec());
-    return d & 0xffffff;
-}
-
-static int get_pmsts(PIIX4PMState *s)
-{
-    int64_t d;
-    int pmsts;
-    pmsts = s->pmsts;
-    d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY,
-                 get_ticks_per_sec());
-    if (d >= s->tmr_overflow_time)
-        s->pmsts |= ACPI_BITMASK_TIMER_STATUS;
-    return s->pmsts;
-}
-
-static void pm_update_sci(PIIX4PMState *s)
-{
-    int sci_level, pmsts;
-    int64_t expire_time;
-
-    pmsts = get_pmsts(s);
-    sci_level = (((pmsts & s->pmen) &
-                  (ACPI_BITMASK_RT_CLOCK_ENABLE |
-                   ACPI_BITMASK_POWER_BUTTON_ENABLE |
-                   ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
-                   ACPI_BITMASK_TIMER_ENABLE)) != 0);
-    qemu_set_irq(s->irq, sci_level);
-    /* schedule a timer interruption if needed */
-    if ((s->pmen & ACPI_BITMASK_TIMER_ENABLE) &&
-        !(pmsts & ACPI_BITMASK_TIMER_STATUS)) {
-        expire_time = muldiv64(s->tmr_overflow_time, get_ticks_per_sec(),
-                               PM_TIMER_FREQUENCY);
-        qemu_mod_timer(s->tmr_timer, expire_time);
-    } else {
-        qemu_del_timer(s->tmr_timer);
-    }
-}
-
-static void pm_tmr_timer(void *opaque)
-{
-    PIIX4PMState *s = opaque;
-    pm_update_sci(s);
-}
-
-static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
-{
-    PIIX4PMState *s = opaque;
-    addr &= 0x3f;
-    switch(addr) {
-    case 0x00:
-        {
-            int64_t d;
-            int pmsts;
-            pmsts = get_pmsts(s);
-            if (pmsts & val & ACPI_BITMASK_TIMER_STATUS) {
-                /* if TMRSTS is reset, then compute the new overflow time */
-                d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY,
-                             get_ticks_per_sec());
-                s->tmr_overflow_time = (d + 0x800000LL) & ~0x7fffffLL;
-            }
-            s->pmsts &= ~val;
-            pm_update_sci(s);
-        }
-        break;
-    case 0x02:
-        s->pmen = val;
-        pm_update_sci(s);
-        break;
-    case 0x04:
-        {
-            int sus_typ;
-            s->pmcntrl = val & ~(ACPI_BITMASK_SLEEP_ENABLE);
-            if (val & ACPI_BITMASK_SLEEP_ENABLE) {
-                /* change suspend type */
-                sus_typ = (val >> 10) & 7;
-                switch(sus_typ) {
-                case 0: /* soft power off */
-                    qemu_system_shutdown_request();
-                    break;
-                case 1:
-                    /* ACPI_BITMASK_WAKE_STATUS should be set on resume.
-                       Pretend that resume was caused by power button */
-                    s->pmsts |= (ACPI_BITMASK_WAKE_STATUS |
-                                 ACPI_BITMASK_POWER_BUTTON_STATUS);
-                    qemu_system_reset_request();
-#if defined(TARGET_I386)
-                    cmos_set_s3_resume();
-#endif
-                default:
-                    break;
-                }
-            }
-        }
-        break;
-    default:
-        break;
-    }
-#ifdef DEBUG
-    printf("PM writew port=0x%04x val=0x%04x\n", addr, val);
-#endif
-}
-
-static uint32_t pm_ioport_readw(void *opaque, uint32_t addr)
-{
-    PIIX4PMState *s = opaque;
-    uint32_t val;
-
-    addr &= 0x3f;
-    switch(addr) {
-    case 0x00:
-        val = get_pmsts(s);
-        break;
-    case 0x02:
-        val = s->pmen;
-        break;
-    case 0x04:
-        val = s->pmcntrl;
-        break;
-    default:
-        val = 0;
-        break;
-    }
-#ifdef DEBUG
-    printf("PM readw port=0x%04x val=0x%04x\n", addr, val);
-#endif
-    return val;
-}
-
-static void pm_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
-{
-    //    PIIX4PMState *s = opaque;
-    addr &= 0x3f;
-#ifdef DEBUG
-    printf("PM writel port=0x%04x val=0x%08x\n", addr, val);
-#endif
-}
-
-static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
-{
-    PIIX4PMState *s = opaque;
-    uint32_t val;
-
-    addr &= 0x3f;
-    switch(addr) {
-    case 0x08:
-        val = get_pmtmr(s);
-        break;
-    default:
-        val = 0;
-        break;
-    }
-#ifdef DEBUG
-    printf("PM readl port=0x%04x val=0x%08x\n", addr, val);
-#endif
-    return val;
-}
-
-static void apm_ctrl_changed(uint32_t val, void *arg)
-{
-    PIIX4PMState *s = arg;
-
-    /* ACPI specs 3.0, 4.7.2.5 */
-    if (val == ACPI_ENABLE) {
-        s->pmcntrl |= ACPI_BITMASK_SCI_ENABLE;
-    } else if (val == ACPI_DISABLE) {
-        s->pmcntrl &= ~ACPI_BITMASK_SCI_ENABLE;
-    }
-
-    if (s->dev.config[0x5b] & (1 << 1)) {
-        cpu_interrupt(first_cpu, CPU_INTERRUPT_SMI);
-    }
-}
-
-static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val)
-{
-#if defined(DEBUG)
-    printf("ACPI: DBG: 0x%08x\n", val);
-#endif
-}
-
-static void pm_io_space_update(PIIX4PMState *s)
-{
-    uint32_t pm_io_base;
-
-    if (s->dev.config[0x80] & 1) {
-        pm_io_base = le32_to_cpu(*(uint32_t *)(s->dev.config + 0x40));
-        pm_io_base &= 0xffc0;
-
-        /* XXX: need to improve memory and ioport allocation */
-#if defined(DEBUG)
-        printf("PM: mapping to 0x%x\n", pm_io_base);
-#endif
-        register_ioport_write(pm_io_base, 64, 2, pm_ioport_writew, s);
-        register_ioport_read(pm_io_base, 64, 2, pm_ioport_readw, s);
-        register_ioport_write(pm_io_base, 64, 4, pm_ioport_writel, s);
-        register_ioport_read(pm_io_base, 64, 4, pm_ioport_readl, s);
-    }
-}
-
-static void pm_write_config(PCIDevice *d,
-                            uint32_t address, uint32_t val, int len)
-{
-    pci_default_write_config(d, address, val, len);
-    if (address == 0x80)
-        pm_io_space_update((PIIX4PMState *)d);
-}
-
-static int vmstate_acpi_post_load(void *opaque)
-{
-    PIIX4PMState *s = opaque;
-
-    pm_io_space_update(s);
-    return 0;
-}
-
-static const VMStateDescription vmstate_acpi = {
-    .name = "piix4_pm",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .post_load = vmstate_acpi_post_load,
-    .fields      = (VMStateField []) {
-        VMSTATE_PCI_DEVICE(dev, PIIX4PMState),
-        VMSTATE_UINT16(pmsts, PIIX4PMState),
-        VMSTATE_UINT16(pmen, PIIX4PMState),
-        VMSTATE_UINT16(pmcntrl, PIIX4PMState),
-        VMSTATE_STRUCT(apm, PIIX4PMState, 0, vmstate_pc_apm, APMState),
-        VMSTATE_TIMER(tmr_timer, PIIX4PMState),
-        VMSTATE_INT64(tmr_overflow_time, PIIX4PMState),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void piix4_reset(void *opaque)
-{
-    PIIX4PMState *s = opaque;
-    uint8_t *pci_conf = s->dev.config;
-
-    pci_conf[0x58] = 0;
-    pci_conf[0x59] = 0;
-    pci_conf[0x5a] = 0;
-    pci_conf[0x5b] = 0;
-
-    if (kvm_enabled()) {
-        /* Mark SMM as already inited (until KVM supports SMM). */
-        pci_conf[0x5B] = 0x02;
-    }
-}
-
-static void piix4_powerdown(void *opaque, int irq, int power_failing)
-{
-#if defined(TARGET_I386)
-    PIIX4PMState *s = opaque;
-
-    if (!s) {
-        qemu_system_shutdown_request();
-    } else if (s->pmen & ACPI_BITMASK_POWER_BUTTON_ENABLE) {
-        s->pmsts |= ACPI_BITMASK_POWER_BUTTON_STATUS;
-        pm_update_sci(s);
-    }
-#endif
-}
-
-i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
-                       qemu_irq sci_irq)
-{
-    PIIX4PMState *s;
-    uint8_t *pci_conf;
-
-    s = (PIIX4PMState *)pci_register_device(bus,
-                                         "PM", sizeof(PIIX4PMState),
-                                         devfn, NULL, pm_write_config);
-    pm_state = s;
-    pci_conf = s->dev.config;
-    pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
-    pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371AB_3);
-    pci_conf[0x06] = 0x80;
-    pci_conf[0x07] = 0x02;
-    pci_conf[0x08] = 0x03; // revision number
-    pci_conf[0x09] = 0x00;
-    pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_OTHER);
-    pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
-    pci_conf[0x3d] = 0x01; // interrupt pin 1
-
-    pci_conf[0x40] = 0x01; /* PM io base read only bit */
-
-    /* APM */
-    apm_init(&s->apm, apm_ctrl_changed, s);
-
-    register_ioport_write(ACPI_DBG_IO_ADDR, 4, 4, acpi_dbg_writel, s);
-
-    if (kvm_enabled()) {
-        /* Mark SMM as already inited to prevent SMM from running.  KVM does not
-         * support SMM mode. */
-        pci_conf[0x5B] = 0x02;
-    }
-
-    /* XXX: which specification is used ? The i82731AB has different
-       mappings */
-    pci_conf[0x5f] = (parallel_hds[0] != NULL ? 0x80 : 0) | 0x10;
-    pci_conf[0x63] = 0x60;
-    pci_conf[0x67] = (serial_hds[0] != NULL ? 0x08 : 0) |
-	(serial_hds[1] != NULL ? 0x90 : 0);
-
-    pci_conf[0x90] = smb_io_base | 1;
-    pci_conf[0x91] = smb_io_base >> 8;
-    pci_conf[0xd2] = 0x09;
-    register_ioport_write(smb_io_base, 64, 1, smb_ioport_writeb, &s->smb);
-    register_ioport_read(smb_io_base, 64, 1, smb_ioport_readb, &s->smb);
-
-    s->tmr_timer = qemu_new_timer(vm_clock, pm_tmr_timer, s);
-
-    qemu_system_powerdown = *qemu_allocate_irqs(piix4_powerdown, s, 1);
-
-    vmstate_register(0, &vmstate_acpi, s);
-
-    pc_smbus_init(&s->smb);
-    s->irq = sci_irq;
-    qemu_register_reset(piix4_reset, s);
-
-    return s->smb.smbus;
-}
-
-#define GPE_BASE 0xafe0
-#define PCI_BASE 0xae00
-#define PCI_EJ_BASE 0xae08
-
-struct gpe_regs {
-    uint16_t sts; /* status */
-    uint16_t en;  /* enabled */
-};
-
-struct pci_status {
-    uint32_t up;
-    uint32_t down;
-};
-
-static struct gpe_regs gpe;
-static struct pci_status pci0_status;
-
-static uint32_t gpe_read_val(uint16_t val, uint32_t addr)
-{
-    if (addr & 1)
-        return (val >> 8) & 0xff;
-    return val & 0xff;
-}
-
-static uint32_t gpe_readb(void *opaque, uint32_t addr)
-{
-    uint32_t val = 0;
-    struct gpe_regs *g = opaque;
-    switch (addr) {
-        case GPE_BASE:
-        case GPE_BASE + 1:
-            val = gpe_read_val(g->sts, addr);
-            break;
-        case GPE_BASE + 2:
-        case GPE_BASE + 3:
-            val = gpe_read_val(g->en, addr);
-            break;
-        default:
-            break;
-    }
-
-#if defined(DEBUG)
-    printf("gpe read %x == %x\n", addr, val);
-#endif
-    return val;
-}
-
-static void gpe_write_val(uint16_t *cur, int addr, uint32_t val)
-{
-    if (addr & 1)
-        *cur = (*cur & 0xff) | (val << 8);
-    else
-        *cur = (*cur & 0xff00) | (val & 0xff);
-}
-
-static void gpe_reset_val(uint16_t *cur, int addr, uint32_t val)
-{
-    uint16_t x1, x0 = val & 0xff;
-    int shift = (addr & 1) ? 8 : 0;
-
-    x1 = (*cur >> shift) & 0xff;
-
-    x1 = x1 & ~x0;
-
-    *cur = (*cur & (0xff << (8 - shift))) | (x1 << shift);
-}
-
-static void gpe_writeb(void *opaque, uint32_t addr, uint32_t val)
-{
-    struct gpe_regs *g = opaque;
-    switch (addr) {
-        case GPE_BASE:
-        case GPE_BASE + 1:
-            gpe_reset_val(&g->sts, addr, val);
-            break;
-        case GPE_BASE + 2:
-        case GPE_BASE + 3:
-            gpe_write_val(&g->en, addr, val);
-            break;
-        default:
-            break;
-   }
-
-#if defined(DEBUG)
-    printf("gpe write %x <== %d\n", addr, val);
-#endif
-}
-
-static uint32_t pcihotplug_read(void *opaque, uint32_t addr)
-{
-    uint32_t val = 0;
-    struct pci_status *g = opaque;
-    switch (addr) {
-        case PCI_BASE:
-            val = g->up;
-            break;
-        case PCI_BASE + 4:
-            val = g->down;
-            break;
-        default:
-            break;
-    }
-
-#if defined(DEBUG)
-    printf("pcihotplug read %x == %x\n", addr, val);
-#endif
-    return val;
-}
-
-static void pcihotplug_write(void *opaque, uint32_t addr, uint32_t val)
-{
-    struct pci_status *g = opaque;
-    switch (addr) {
-        case PCI_BASE:
-            g->up = val;
-            break;
-        case PCI_BASE + 4:
-            g->down = val;
-            break;
-   }
-
-#if defined(DEBUG)
-    printf("pcihotplug write %x <== %d\n", addr, val);
-#endif
-}
-
-static uint32_t pciej_read(void *opaque, uint32_t addr)
-{
-#if defined(DEBUG)
-    printf("pciej read %x\n", addr);
-#endif
-    return 0;
-}
-
-static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
-{
-#if defined (TARGET_I386)
-    int slot = ffs(val) - 1;
-
-    pci_device_hot_remove_success(0, slot);
-#endif
-
-#if defined(DEBUG)
-    printf("pciej write %x <== %d\n", addr, val);
-#endif
-}
-
-static void piix4_device_hot_add(int bus, int slot, int state);
-
-void piix4_acpi_system_hot_add_init(void)
-{
-    register_ioport_write(GPE_BASE, 4, 1, gpe_writeb, &gpe);
-    register_ioport_read(GPE_BASE, 4, 1,  gpe_readb, &gpe);
-
-    register_ioport_write(PCI_BASE, 8, 4, pcihotplug_write, &pci0_status);
-    register_ioport_read(PCI_BASE, 8, 4,  pcihotplug_read, &pci0_status);
-
-    register_ioport_write(PCI_EJ_BASE, 4, 4, pciej_write, NULL);
-    register_ioport_read(PCI_EJ_BASE, 4, 4,  pciej_read, NULL);
-
-    qemu_system_device_hot_add_register(piix4_device_hot_add);
-}
-
-static void enable_device(struct pci_status *p, struct gpe_regs *g, int slot)
-{
-    g->sts |= 2;
-    p->up |= (1 << slot);
-}
-
-static void disable_device(struct pci_status *p, struct gpe_regs *g, int slot)
-{
-    g->sts |= 2;
-    p->down |= (1 << slot);
-}
-
-static void piix4_device_hot_add(int bus, int slot, int state)
-{
-    pci0_status.up = 0;
-    pci0_status.down = 0;
-    if (state)
-        enable_device(&pci0_status, &gpe, slot);
-    else
-        disable_device(&pci0_status, &gpe, slot);
-    if (gpe.en & 2) {
-        qemu_set_irq(pm_state->irq, 1);
-        qemu_set_irq(pm_state->irq, 0);
-    }
-}
-
 static qemu_system_device_hot_add_t device_hot_add_callback;
 void qemu_system_device_hot_add_register(qemu_system_device_hot_add_t callback)
 {
diff --git a/hw/acpi.c b/hw/acpi_piix4.c
similarity index 74%
copy from hw/acpi.c
copy to hw/acpi_piix4.c
index e88a83b..429afd9 100644
--- a/hw/acpi.c
+++ b/hw/acpi_piix4.c
@@ -55,7 +55,8 @@ static PIIX4PMState *pm_state;
 static uint32_t get_pmtmr(PIIX4PMState *s)
 {
     uint32_t d;
-    d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY, get_ticks_per_sec());
+    d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY,
+                 get_ticks_per_sec());
     return d & 0xffffff;
 }
 
@@ -265,10 +266,11 @@ static void pm_write_config(PCIDevice *d,
 
 static int vmstate_acpi_post_load(void *opaque)
 {
-    PIIX4PMState *s = opaque;
+     PIIX4PMState *s = opaque;
 
-    pm_io_space_update(s);
-    return 0;
+     pm_io_space_update(s);
+
+     return 0;
 }
 
 static const VMStateDescription vmstate_acpi = {
@@ -567,184 +569,3 @@ static void piix4_device_hot_add(int bus, int slot, int state)
         qemu_set_irq(pm_state->irq, 0);
     }
 }
-
-static qemu_system_device_hot_add_t device_hot_add_callback;
-void qemu_system_device_hot_add_register(qemu_system_device_hot_add_t callback)
-{
-    device_hot_add_callback = callback;
-}
-
-void qemu_system_device_hot_add(int pcibus, int slot, int state)
-{
-    if (device_hot_add_callback)
-        device_hot_add_callback(pcibus, slot, state);
-}
-
-struct acpi_table_header
-{
-    char signature [4];    /* 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 */
-    char oem_id [6];       /* OEM identification */
-    char oem_table_id [8]; /* OEM table identification */
-    uint32_t oem_revision;    /* OEM revision number */
-    char asl_compiler_id [4]; /* ASL compiler vendor ID */
-    uint32_t asl_compiler_revision; /* ASL compiler revision number */
-} __attribute__((packed));
-
-char *acpi_tables;
-size_t acpi_tables_len;
-
-static int acpi_checksum(const uint8_t *data, int len)
-{
-    int sum, i;
-    sum = 0;
-    for(i = 0; i < len; i++)
-        sum += data[i];
-    return (-sum) & 0xff;
-}
-
-int acpi_table_add(const char *t)
-{
-    static const char *dfl_id = "QEMUQEMU";
-    char buf[1024], *p, *f;
-    struct acpi_table_header acpi_hdr;
-    unsigned long val;
-    size_t off;
-
-    memset(&acpi_hdr, 0, sizeof(acpi_hdr));
-  
-    if (get_param_value(buf, sizeof(buf), "sig", t)) {
-        strncpy(acpi_hdr.signature, buf, 4);
-    } else {
-        strncpy(acpi_hdr.signature, dfl_id, 4);
-    }
-    if (get_param_value(buf, sizeof(buf), "rev", t)) {
-        val = strtoul(buf, &p, 10);
-        if (val > 255 || *p != '\0')
-            goto out;
-    } else {
-        val = 1;
-    }
-    acpi_hdr.revision = (int8_t)val;
-
-    if (get_param_value(buf, sizeof(buf), "oem_id", t)) {
-        strncpy(acpi_hdr.oem_id, buf, 6);
-    } else {
-        strncpy(acpi_hdr.oem_id, dfl_id, 6);
-    }
-
-    if (get_param_value(buf, sizeof(buf), "oem_table_id", t)) {
-        strncpy(acpi_hdr.oem_table_id, buf, 8);
-    } else {
-        strncpy(acpi_hdr.oem_table_id, dfl_id, 8);
-    }
-
-    if (get_param_value(buf, sizeof(buf), "oem_rev", t)) {
-        val = strtol(buf, &p, 10);
-        if(*p != '\0')
-            goto out;
-    } else {
-        val = 1;
-    }
-    acpi_hdr.oem_revision = cpu_to_le32(val);
-
-    if (get_param_value(buf, sizeof(buf), "asl_compiler_id", t)) {
-        strncpy(acpi_hdr.asl_compiler_id, buf, 4);
-    } else {
-        strncpy(acpi_hdr.asl_compiler_id, dfl_id, 4);
-    }
-
-    if (get_param_value(buf, sizeof(buf), "asl_compiler_rev", t)) {
-        val = strtol(buf, &p, 10);
-        if(*p != '\0')
-            goto out;
-    } else {
-        val = 1;
-    }
-    acpi_hdr.asl_compiler_revision = cpu_to_le32(val);
-    
-    if (!get_param_value(buf, sizeof(buf), "data", t)) {
-         buf[0] = '\0';
-    }
-
-    acpi_hdr.length = sizeof(acpi_hdr);
-
-    f = buf;
-    while (buf[0]) {
-        struct stat s;
-        char *n = strchr(f, ':');
-        if (n)
-            *n = '\0';
-        if(stat(f, &s) < 0) {
-            fprintf(stderr, "Can't stat file '%s': %s\n", f, strerror(errno));
-            goto out;
-        }
-        acpi_hdr.length += s.st_size;
-        if (!n)
-            break;
-        *n = ':';
-        f = n + 1;
-    }
-
-    if (!acpi_tables) {
-        acpi_tables_len = sizeof(uint16_t);
-        acpi_tables = qemu_mallocz(acpi_tables_len);
-    }
-    p = acpi_tables + acpi_tables_len;
-    acpi_tables_len += sizeof(uint16_t) + acpi_hdr.length;
-    acpi_tables = qemu_realloc(acpi_tables, acpi_tables_len);
-
-    acpi_hdr.length = cpu_to_le32(acpi_hdr.length);
-    *(uint16_t*)p = acpi_hdr.length;
-    p += sizeof(uint16_t);
-    memcpy(p, &acpi_hdr, sizeof(acpi_hdr));
-    off = sizeof(acpi_hdr);
-
-    f = buf;
-    while (buf[0]) {
-        struct stat s;
-        int fd;
-        char *n = strchr(f, ':');
-        if (n)
-            *n = '\0';
-        fd = open(f, O_RDONLY);
-
-        if(fd < 0)
-            goto out;
-        if(fstat(fd, &s) < 0) {
-            close(fd);
-            goto out;
-        }
-
-        do {
-            int r;
-            r = read(fd, p + off, s.st_size);
-            if (r > 0) {
-                off += r;
-                s.st_size -= r;
-            } else if ((r < 0 && errno != EINTR) || r == 0) {
-                close(fd);
-                goto out;
-            }
-        } while(s.st_size);
-
-        close(fd);
-        if (!n)
-            break;
-        f = n + 1;
-    }
-
-    ((struct acpi_table_header*)p)->checksum = acpi_checksum((uint8_t*)p, off);
-    /* increase number of tables */
-    (*(uint16_t*)acpi_tables) =
-	    cpu_to_le32(le32_to_cpu(*(uint16_t*)acpi_tables) + 1);
-    return 0;
-out:
-    if (acpi_tables) {
-        free(acpi_tables);
-        acpi_tables = NULL;
-    }
-    return -1;
-}
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 05/61] acpi_piix4: remove unused variable in get_pmsts().
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (3 preceding siblings ...)
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 04/61] acpi: split acpi.c into the common part and the piix4 part Isaku Yamahata
@ 2009-09-30 10:17 ` Isaku Yamahata
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 06/61] pc: fix file stream leak in multiboot loader Isaku Yamahata
                   ` (59 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:17 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

remove unused variable in get_pmsts().

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/acpi_piix4.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 429afd9..5f3ee9a 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -63,8 +63,6 @@ static uint32_t get_pmtmr(PIIX4PMState *s)
 static int get_pmsts(PIIX4PMState *s)
 {
     int64_t d;
-    int pmsts;
-    pmsts = s->pmsts;
     d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY,
                  get_ticks_per_sec());
     if (d >= s->tmr_overflow_time)
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 06/61] pc: fix file stream leak in multiboot loader.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (4 preceding siblings ...)
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 05/61] acpi_piix4: remove unused variable in get_pmsts() Isaku Yamahata
@ 2009-09-30 10:17 ` Isaku Yamahata
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 07/61] pc, i440fx: Make smm enable/disable function i440fx independent Isaku Yamahata
                   ` (58 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:17 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

fix file stream leak in load_multiboot() in pc.c
There is no reason to keep them open.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pc.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/hw/pc.c b/hw/pc.c
index bc2875e..0d85914 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -754,6 +754,7 @@ static int load_multiboot(void *fw_cfg,
                             initrd_filename, mb_mod_length);
                     exit(1);
                 }
+                fclose(f);
 
                 mb_mod_count++;
                 stl_phys(mb_mod_info + 0, mb_mod_start);
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 07/61] pc, i440fx: Make smm enable/disable function i440fx independent.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (5 preceding siblings ...)
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 06/61] pc: fix file stream leak in multiboot loader Isaku Yamahata
@ 2009-09-30 10:17 ` Isaku Yamahata
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 08/61] pc: make an unnecessary global variable, pit, local Isaku Yamahata
                   ` (57 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:17 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

make cpu_smm_update() generic to be independent on i440fx by
registering a callback.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pc.c       |   18 +++++++++++++++---
 hw/pc.h       |    8 +++++++-
 hw/piix_pci.c |    6 ++++--
 3 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/hw/pc.c b/hw/pc.c
index 0d85914..232f6a7 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -64,7 +64,6 @@
 static fdctrl_t *floppy_controller;
 static RTCState *rtc_state;
 static PITState *pit;
-static PCII440FXState *i440fx_state;
 
 typedef struct rom_reset_data {
     uint8_t *data;
@@ -130,10 +129,22 @@ uint64_t cpu_get_tsc(CPUX86State *env)
 }
 
 /* SMM support */
+
+static cpu_set_smm_t smm_set;
+static void *smm_arg;
+
+void cpu_smm_register(cpu_set_smm_t callback, void *arg)
+{
+    assert(smm_set == NULL);
+    assert(smm_arg == NULL);
+    smm_set = callback;
+    smm_arg = arg;
+}
+
 void cpu_smm_update(CPUState *env)
 {
-    if (i440fx_state && env == first_cpu)
-        i440fx_set_smm(i440fx_state, (env->hflags >> HF_SMM_SHIFT) & 1);
+    if (smm_set && smm_arg && env == first_cpu)
+        smm_set(!!(env->hflags & HF_SMM_MASK), smm_arg);
 }
 
 
@@ -1128,6 +1139,7 @@ static void pc_init1(ram_addr_t ram_size,
     int bios_size, isa_bios_size, oprom_area_size;
     PCIBus *pci_bus;
     ISADevice *isa_dev;
+    PCII440FXState *i440fx_state;
     int piix3_devfn = -1;
     CPUState *env;
     qemu_irq *cpu_irq;
diff --git a/hw/pc.h b/hw/pc.h
index c9cdd4a..818323e 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -94,6 +94,13 @@ extern int fd_bootchk;
 void ioport_set_a20(int enable);
 int ioport_get_a20(void);
 
+typedef void (*cpu_set_smm_t)(int smm, void *arg);
+#if defined(TARGET_I386)
+void cpu_smm_register(cpu_set_smm_t callback, void *arg);
+#else
+static inline void cpu_smm_register(cpu_set_smm_t callback, void *arg) { };
+#endif
+
 /* acpi.c */
 extern int acpi_enabled;
 extern char *acpi_tables;
@@ -120,7 +127,6 @@ struct PCII440FXState;
 typedef struct PCII440FXState PCII440FXState;
 
 PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn, qemu_irq *pic);
-void i440fx_set_smm(PCII440FXState *d, int val);
 void i440fx_init_memory_mappings(PCII440FXState *d);
 
 /* piix4.c */
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index edd6df0..7447663 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -122,8 +122,10 @@ static void i440fx_update_memory_mappings(PCII440FXState *d)
     }
 }
 
-void i440fx_set_smm(PCII440FXState *d, int val)
+static void i440fx_set_smm(int val, void *arg)
 {
+    PCII440FXState *d = arg;
+
     val = (val != 0);
     if (d->smm_enabled != val) {
         d->smm_enabled = val;
@@ -131,7 +133,6 @@ void i440fx_set_smm(PCII440FXState *d, int val)
     }
 }
 
-
 /* XXX: suppress when better memory API. We make the assumption that
    no device (in particular the VGA) changes the memory mappings in
    the 0xa0000-0x100000 range */
@@ -223,6 +224,7 @@ static int i440fx_initfn(PCIDevice *dev)
     d->dev.config[0x72] = 0x02; /* SMRAM */
 
     vmstate_register(0, &vmstate_i440fx, d);
+    cpu_smm_register(&i440fx_set_smm, d);
     return 0;
 }
 
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 08/61] pc: make an unnecessary global variable, pit, local.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (6 preceding siblings ...)
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 07/61] pc, i440fx: Make smm enable/disable function i440fx independent Isaku Yamahata
@ 2009-09-30 10:17 ` Isaku Yamahata
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 09/61] pc: remove a global variable, floppy_controller Isaku Yamahata
                   ` (56 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:17 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

remove unnecessary global static variables, pit.
Make it local.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pc.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/hw/pc.c b/hw/pc.c
index 232f6a7..1a2b2b4 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -63,7 +63,6 @@
 
 static fdctrl_t *floppy_controller;
 static RTCState *rtc_state;
-static PITState *pit;
 
 typedef struct rom_reset_data {
     uint8_t *data;
@@ -1151,6 +1150,7 @@ static void pc_init1(ram_addr_t ram_size,
     BlockDriverState *fd[MAX_FD];
     int using_vga = cirrus_vga_enabled || std_vga_enabled || vmsvga_enabled;
     void *fw_cfg;
+    PITState *pit;
 
     if (ram_size >= 0xe0000000 ) {
         above_4g_mem_size = ram_size - 0xe0000000;
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 09/61] pc: remove a global variable, floppy_controller.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (7 preceding siblings ...)
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 08/61] pc: make an unnecessary global variable, pit, local Isaku Yamahata
@ 2009-09-30 10:17 ` Isaku Yamahata
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 10/61] pc: remove a global variable, RTCState *rtc_state Isaku Yamahata
                   ` (55 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:17 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

Remove a global variable, floppy_controller.
Since it is unnecessarily global, make it local and pass it as
a function argument.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pc.c |    8 +++++---
 1 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/hw/pc.c b/hw/pc.c
index 1a2b2b4..4d301ff 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -61,7 +61,6 @@
 
 #define MAX_IDE_BUS 2
 
-static fdctrl_t *floppy_controller;
 static RTCState *rtc_state;
 
 typedef struct rom_reset_data {
@@ -277,7 +276,8 @@ static int pc_boot_set(void *opaque, const char *boot_device)
 
 /* hd_table must contain 4 block drivers */
 static void cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
-                      const char *boot_device, DriveInfo **hd_table)
+                      const char *boot_device, DriveInfo **hd_table,
+                      fdctrl_t *floppy_controller)
 {
     RTCState *s = rtc_state;
     int nbds, bds[3] = { 0, };
@@ -1150,6 +1150,7 @@ static void pc_init1(ram_addr_t ram_size,
     BlockDriverState *fd[MAX_FD];
     int using_vga = cirrus_vga_enabled || std_vga_enabled || vmsvga_enabled;
     void *fw_cfg;
+    fdctrl_t *floppy_controller;
     PITState *pit;
 
     if (ram_size >= 0xe0000000 ) {
@@ -1399,7 +1400,8 @@ static void pc_init1(ram_addr_t ram_size,
     }
     floppy_controller = fdctrl_init_isa(fd);
 
-    cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd);
+    cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd,
+              floppy_controller);
 
     if (pci_enabled && usb_enabled) {
         usb_uhci_piix3_init(pci_bus, piix3_devfn + 2);
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 10/61] pc: remove a global variable, RTCState *rtc_state.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (8 preceding siblings ...)
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 09/61] pc: remove a global variable, floppy_controller Isaku Yamahata
@ 2009-09-30 10:17 ` Isaku Yamahata
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 11/61] pc: introduce a function to allocate cpu irq Isaku Yamahata
                   ` (54 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:17 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata, Paolo Bonzini

remove a global variable, RTCState *rtc_state.
Only the cmos_set_s3_resume_init() needs it global.
So introduce a registering function and make it local.
As for other function which references the variable, pass it
as a function argument.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
Cc: Paolo Bonzini <bonzini@gnu.org>
---
 hw/pc.c |   25 ++++++++++++++++---------
 hw/pc.h |    1 +
 2 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/hw/pc.c b/hw/pc.c
index 4d301ff..432f14b 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -61,8 +61,6 @@
 
 #define MAX_IDE_BUS 2
 
-static RTCState *rtc_state;
-
 typedef struct rom_reset_data {
     uint8_t *data;
     target_phys_addr_t addr;
@@ -212,9 +210,9 @@ static int cmos_get_fd_drive_type(int fd0)
     return val;
 }
 
-static void cmos_init_hd(int type_ofs, int info_ofs, BlockDriverState *hd)
+static void cmos_init_hd(int type_ofs, int info_ofs, BlockDriverState *hd,
+                         RTCState *s)
 {
-    RTCState *s = rtc_state;
     int cylinders, heads, sectors;
     bdrv_get_geometry_hint(hd, &cylinders, &heads, &sectors);
     rtc_set_memory(s, type_ofs, 47);
@@ -277,9 +275,8 @@ static int pc_boot_set(void *opaque, const char *boot_device)
 /* hd_table must contain 4 block drivers */
 static void cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
                       const char *boot_device, DriveInfo **hd_table,
-                      fdctrl_t *floppy_controller)
+                      fdctrl_t *floppy_controller, RTCState *s)
 {
-    RTCState *s = rtc_state;
     int nbds, bds[3] = { 0, };
     int val;
     int fd0, fd1, nb;
@@ -368,9 +365,9 @@ static void cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
 
     rtc_set_memory(s, 0x12, (hd_table[0] ? 0xf0 : 0) | (hd_table[1] ? 0x0f : 0));
     if (hd_table[0])
-        cmos_init_hd(0x19, 0x1b, hd_table[0]->bdrv);
+        cmos_init_hd(0x19, 0x1b, hd_table[0]->bdrv, s);
     if (hd_table[1])
-        cmos_init_hd(0x1a, 0x24, hd_table[1]->bdrv);
+        cmos_init_hd(0x1a, 0x24, hd_table[1]->bdrv, s);
 
     val = 0;
     for (i = 0; i < 4; i++) {
@@ -1151,6 +1148,7 @@ static void pc_init1(ram_addr_t ram_size,
     int using_vga = cirrus_vga_enabled || std_vga_enabled || vmsvga_enabled;
     void *fw_cfg;
     fdctrl_t *floppy_controller;
+    RTCState *rtc_state;
     PITState *pit;
 
     if (ram_size >= 0xe0000000 ) {
@@ -1330,6 +1328,7 @@ static void pc_init1(ram_addr_t ram_size,
     }
 
     rtc_state = rtc_init(2000);
+    cmos_set_s3_resume_init(rtc_state);
 
     qemu_register_boot_set(pc_boot_set, rtc_state);
 
@@ -1401,7 +1400,7 @@ static void pc_init1(ram_addr_t ram_size,
     floppy_controller = fdctrl_init_isa(fd);
 
     cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd,
-              floppy_controller);
+              floppy_controller, rtc_state);
 
     if (pci_enabled && usb_enabled) {
         usb_uhci_piix3_init(pci_bus, piix3_devfn + 2);
@@ -1475,10 +1474,18 @@ static void pc_init_isa(ram_addr_t ram_size,
 
 /* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE)
    BIOS will read it and start S3 resume at POST Entry */
+static RTCState *rtc_state;
+void cmos_set_s3_resume_init(RTCState *s)
+{
+    rtc_state = s;
+}
+
 void cmos_set_s3_resume(void)
 {
+#if defined(TARGET_I386)
     if (rtc_state)
         rtc_set_memory(rtc_state, 0xF, 0xFE);
+#endif
 }
 
 static QEMUMachine pc_machine = {
diff --git a/hw/pc.h b/hw/pc.h
index 818323e..d381a86 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -86,6 +86,7 @@ RTCState *rtc_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq,
                       int base_year);
 void rtc_set_memory(RTCState *s, int addr, int val);
 void rtc_set_date(RTCState *s, const struct tm *tm);
+void cmos_set_s3_resume_init(RTCState *s);
 void cmos_set_s3_resume(void);
 
 /* pc.c */
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 11/61] pc: introduce a function to allocate cpu irq.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (9 preceding siblings ...)
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 10/61] pc: remove a global variable, RTCState *rtc_state Isaku Yamahata
@ 2009-09-30 10:17 ` Isaku Yamahata
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 12/61] pc: make pc_init1() not refer ferr_irq directly Isaku Yamahata
                   ` (53 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:17 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

Introduce a function, pc_allocate_cpu_irq(), to allocate cpu irq
in order to make pic_irq_request() piix independent.
Later piix code will be split out to another file keeping pic_irq_request()
static.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pc.c |    7 ++++++-
 1 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/hw/pc.c b/hw/pc.c
index 432f14b..6f42907 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1119,6 +1119,11 @@ static CPUState *pc_new_cpu(const char *cpu_model)
     return env;
 }
 
+static qemu_irq *pc_allocate_cpu_irq(void)
+{
+    return qemu_allocate_irqs(pic_irq_request, NULL, 1);
+}
+
 /* PC hardware initialisation */
 static void pc_init1(ram_addr_t ram_size,
                      const char *boot_device,
@@ -1287,7 +1292,7 @@ static void pc_init1(ram_addr_t ram_size,
                                            0xe0000);
     }
 
-    cpu_irq = qemu_allocate_irqs(pic_irq_request, NULL, 1);
+    cpu_irq = pc_allocate_cpu_irq();
     i8259 = i8259_init(cpu_irq[0]);
     isa_irq_state = qemu_mallocz(sizeof(*isa_irq_state));
     isa_irq_state->i8259 = i8259;
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 12/61] pc: make pc_init1() not refer ferr_irq directly.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (10 preceding siblings ...)
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 11/61] pc: introduce a function to allocate cpu irq Isaku Yamahata
@ 2009-09-30 10:17 ` Isaku Yamahata
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 13/61] pc: split out cpu initialization from pc_init1() into pc_cpus_init() Isaku Yamahata
                   ` (52 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:17 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

By introducing a registering function, make pc_init1() not refer to
ferr_irq directly in order to make ferr_irq piix independent.
Later pc_init1() will be split out into another file keeping ferr_irq
static.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pc.c |    8 +++++++-
 hw/pc.h |    2 ++
 2 files changed, 9 insertions(+), 1 deletions(-)

diff --git a/hw/pc.c b/hw/pc.c
index 6f42907..a5e97ac 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -107,6 +107,12 @@ static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
 
 /* MSDOS compatibility mode FPU exception support */
 static qemu_irq ferr_irq;
+
+void pc_register_ferr_irq(qemu_irq irq)
+{
+    ferr_irq = irq;
+}
+
 /* XXX: add IGNNE support */
 void cpu_set_ferr(CPUX86State *s)
 {
@@ -1306,7 +1312,7 @@ static void pc_init1(ram_addr_t ram_size,
     }
     isa_bus_irqs(isa_irq);
 
-    ferr_irq = isa_reserve_irq(13);
+    pc_register_ferr_irq(isa_reserve_irq(13));
 
     /* init basic PC hardware */
     register_ioport_write(0x80, 1, 1, ioport80_write, NULL);
diff --git a/hw/pc.h b/hw/pc.h
index d381a86..90acd75 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -92,6 +92,8 @@ void cmos_set_s3_resume(void);
 /* pc.c */
 extern int fd_bootchk;
 
+void pc_register_ferr_irq(qemu_irq irq);
+
 void ioport_set_a20(int enable);
 int ioport_get_a20(void);
 
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 13/61] pc: split out cpu initialization from pc_init1() into pc_cpus_init().
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (11 preceding siblings ...)
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 12/61] pc: make pc_init1() not refer ferr_irq directly Isaku Yamahata
@ 2009-09-30 10:17 ` Isaku Yamahata
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 14/61] pc: split out memory allocation from pc_init1() into pc_memory_init() Isaku Yamahata
                   ` (51 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:17 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

split out cpu initialization which is piix independent from pc_init1()
into pc_cpus_init(). Later it will be used.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pc.c |   32 +++++++++++++++++++-------------
 1 files changed, 19 insertions(+), 13 deletions(-)

diff --git a/hw/pc.c b/hw/pc.c
index a5e97ac..10847ae 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1125,6 +1125,24 @@ static CPUState *pc_new_cpu(const char *cpu_model)
     return env;
 }
 
+static void pc_cpus_init(const char *cpu_model)
+{
+    int i;
+
+    /* init CPUs */
+    if (cpu_model == NULL) {
+#ifdef TARGET_X86_64
+        cpu_model = "qemu64";
+#else
+        cpu_model = "qemu32";
+#endif
+    }
+
+    for(i = 0; i < smp_cpus; i++) {
+        (void)pc_new_cpu(cpu_model);
+    }
+}
+
 static qemu_irq *pc_allocate_cpu_irq(void)
 {
     return qemu_allocate_irqs(pic_irq_request, NULL, 1);
@@ -1148,7 +1166,6 @@ static void pc_init1(ram_addr_t ram_size,
     ISADevice *isa_dev;
     PCII440FXState *i440fx_state;
     int piix3_devfn = -1;
-    CPUState *env;
     qemu_irq *cpu_irq;
     qemu_irq *isa_irq;
     qemu_irq *i8259;
@@ -1171,18 +1188,7 @@ static void pc_init1(ram_addr_t ram_size,
 
     linux_boot = (kernel_filename != NULL);
 
-    /* init CPUs */
-    if (cpu_model == NULL) {
-#ifdef TARGET_X86_64
-        cpu_model = "qemu64";
-#else
-        cpu_model = "qemu32";
-#endif
-    }
-
-    for (i = 0; i < smp_cpus; i++) {
-        env = pc_new_cpu(cpu_model);
-    }
+    pc_cpus_init(cpu_model);
 
     vmport_init();
 
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 14/61] pc: split out memory allocation from pc_init1() into pc_memory_init()
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (12 preceding siblings ...)
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 13/61] pc: split out cpu initialization from pc_init1() into pc_cpus_init() Isaku Yamahata
@ 2009-09-30 10:17 ` Isaku Yamahata
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 15/61] pc: split out vga initialization from pc_init1() into pc_vga_init() Isaku Yamahata
                   ` (50 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:17 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

Split out memory allocation and rom/bios loading which doesn't depend
on piix from pc_init1() into pc_memory_init().
Later it will be used.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pc.c |   69 +++++++++++++++++++++++++++++++++++++++-----------------------
 1 files changed, 43 insertions(+), 26 deletions(-)

diff --git a/hw/pc.c b/hw/pc.c
index 10847ae..b987b34 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1148,36 +1148,20 @@ static qemu_irq *pc_allocate_cpu_irq(void)
     return qemu_allocate_irqs(pic_irq_request, NULL, 1);
 }
 
-/* PC hardware initialisation */
-static void pc_init1(ram_addr_t ram_size,
-                     const char *boot_device,
-                     const char *kernel_filename,
-                     const char *kernel_cmdline,
-                     const char *initrd_filename,
-                     const char *cpu_model,
-                     int pci_enabled)
+static void pc_memory_init(ram_addr_t ram_size,
+                           const char *kernel_filename,
+                           const char *kernel_cmdline,
+                           const char *initrd_filename,
+                           ram_addr_t *below_4g_mem_size_p,
+                           ram_addr_t *above_4g_mem_size_p)
 {
     char *filename;
     int ret, linux_boot, i;
     ram_addr_t ram_addr, bios_offset, option_rom_offset;
     ram_addr_t below_4g_mem_size, above_4g_mem_size = 0;
     int bios_size, isa_bios_size, oprom_area_size;
-    PCIBus *pci_bus;
-    ISADevice *isa_dev;
-    PCII440FXState *i440fx_state;
-    int piix3_devfn = -1;
-    qemu_irq *cpu_irq;
-    qemu_irq *isa_irq;
-    qemu_irq *i8259;
-    IsaIrqState *isa_irq_state;
-    DriveInfo *dinfo;
-    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
-    BlockDriverState *fd[MAX_FD];
     int using_vga = cirrus_vga_enabled || std_vga_enabled || vmsvga_enabled;
     void *fw_cfg;
-    fdctrl_t *floppy_controller;
-    RTCState *rtc_state;
-    PITState *pit;
 
     if (ram_size >= 0xe0000000 ) {
         above_4g_mem_size = ram_size - 0xe0000000;
@@ -1185,13 +1169,11 @@ static void pc_init1(ram_addr_t ram_size,
     } else {
         below_4g_mem_size = ram_size;
     }
+    *above_4g_mem_size_p = above_4g_mem_size;
+    *below_4g_mem_size_p = below_4g_mem_size;
 
     linux_boot = (kernel_filename != NULL);
 
-    pc_cpus_init(cpu_model);
-
-    vmport_init();
-
     /* allocate RAM */
     ram_addr = qemu_ram_alloc(0xa0000);
     cpu_register_physical_memory(0, 0xa0000, ram_addr);
@@ -1303,6 +1285,41 @@ static void pc_init1(ram_addr_t ram_size,
         oprom_area_size += load_option_rom(nic_oprom, 0xc0000 + oprom_area_size,
                                            0xe0000);
     }
+}
+
+/* PC hardware initialisation */
+static void pc_init1(ram_addr_t ram_size,
+                     const char *boot_device,
+                     const char *kernel_filename,
+                     const char *kernel_cmdline,
+                     const char *initrd_filename,
+                     const char *cpu_model,
+                     int pci_enabled)
+{
+    int i;
+    ram_addr_t below_4g_mem_size, above_4g_mem_size;
+    PCIBus *pci_bus;
+    ISADevice *isa_dev;
+    PCII440FXState *i440fx_state;
+    int piix3_devfn = -1;
+    qemu_irq *cpu_irq;
+    qemu_irq *isa_irq;
+    qemu_irq *i8259;
+    IsaIrqState *isa_irq_state;
+    DriveInfo *dinfo;
+    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
+    BlockDriverState *fd[MAX_FD];
+    fdctrl_t *floppy_controller;
+    RTCState *rtc_state;
+    PITState *pit;
+
+    pc_cpus_init(cpu_model);
+
+    vmport_init();
+
+    /* allocate ram and load rom/bios */
+    pc_memory_init(ram_size, kernel_filename, kernel_cmdline, initrd_filename,
+                   &below_4g_mem_size, &above_4g_mem_size);
 
     cpu_irq = pc_allocate_cpu_irq();
     i8259 = i8259_init(cpu_irq[0]);
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 15/61] pc: split out vga initialization from pc_init1() into pc_vga_init().
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (13 preceding siblings ...)
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 14/61] pc: split out memory allocation from pc_init1() into pc_memory_init() Isaku Yamahata
@ 2009-09-30 10:17 ` Isaku Yamahata
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 16/61] pc: split out basic device init from pc_init1() into pc_basic_device_init() Isaku Yamahata
                   ` (49 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:17 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

Split out vga initialization which is independent of piix
from pc_init1() as pc_vga_init().
Later it will be used.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pc.c |   41 +++++++++++++++++++++++------------------
 1 files changed, 23 insertions(+), 18 deletions(-)

diff --git a/hw/pc.c b/hw/pc.c
index b987b34..5c461a6 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1287,6 +1287,28 @@ static void pc_memory_init(ram_addr_t ram_size,
     }
 }
 
+static void pc_vga_init(PCIBus *pci_bus)
+{
+    if (cirrus_vga_enabled) {
+        if (pci_bus) {
+            pci_cirrus_vga_init(pci_bus);
+        } else {
+            isa_cirrus_vga_init();
+        }
+    } else if (vmsvga_enabled) {
+        if (pci_bus)
+            pci_vmsvga_init(pci_bus);
+        else
+            fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __FUNCTION__);
+    } else if (std_vga_enabled) {
+        if (pci_bus) {
+            pci_vga_init(pci_bus, 0, 0);
+        } else {
+            isa_vga_init();
+        }
+    }
+}
+
 /* PC hardware initialisation */
 static void pc_init1(ram_addr_t ram_size,
                      const char *boot_device,
@@ -1342,24 +1364,7 @@ static void pc_init1(ram_addr_t ram_size,
 
     register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
 
-    if (cirrus_vga_enabled) {
-        if (pci_enabled) {
-            pci_cirrus_vga_init(pci_bus);
-        } else {
-            isa_cirrus_vga_init();
-        }
-    } else if (vmsvga_enabled) {
-        if (pci_enabled)
-            pci_vmsvga_init(pci_bus);
-        else
-            fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __FUNCTION__);
-    } else if (std_vga_enabled) {
-        if (pci_enabled) {
-            pci_vga_init(pci_bus, 0, 0);
-        } else {
-            isa_vga_init();
-        }
-    }
+    pc_vga_init(pci_enabled? pci_bus: NULL);
 
     rtc_state = rtc_init(2000);
     cmos_set_s3_resume_init(rtc_state);
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 16/61] pc: split out basic device init from pc_init1() into pc_basic_device_init()
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (14 preceding siblings ...)
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 15/61] pc: split out vga initialization from pc_init1() into pc_vga_init() Isaku Yamahata
@ 2009-09-30 10:17 ` Isaku Yamahata
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 17/61] pc: split out pci device init from pc_init1() into pc_pci_device_init() Isaku Yamahata
                   ` (48 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:17 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

Split out basic device, i.e. legacy devices like floppy, initialization
from pc_init1() into pc_basic_device_init().
Later it will be used.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pc.c |   97 +++++++++++++++++++++++++++++++++++----------------------------
 1 files changed, 54 insertions(+), 43 deletions(-)

diff --git a/hw/pc.c b/hw/pc.c
index 5c461a6..380a66f 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1309,6 +1309,58 @@ static void pc_vga_init(PCIBus *pci_bus)
     }
 }
 
+static void pc_basic_device_init(qemu_irq *isa_irq,
+                                 ISADevice **isa_dev,
+                                 fdctrl_t **floppy_controller,
+                                 RTCState **rtc_state)
+{
+    int i;
+    DriveInfo *dinfo;
+    BlockDriverState *fd[MAX_FD];
+    PITState *pit;
+
+    register_ioport_write(0x80, 1, 1, ioport80_write, NULL);
+
+    register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
+
+    *rtc_state = rtc_init(2000);
+    cmos_set_s3_resume_init(*rtc_state);
+
+    qemu_register_boot_set(pc_boot_set, *rtc_state);
+
+    register_ioport_read(0x92, 1, 1, ioport92_read, NULL);
+    register_ioport_write(0x92, 1, 1, ioport92_write, NULL);
+
+    pit = pit_init(0x40, isa_reserve_irq(0));
+    pcspk_init(pit);
+    if (!no_hpet) {
+        hpet_init(isa_irq);
+    }
+
+    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
+        if (serial_hds[i]) {
+            serial_init(serial_io[i], isa_reserve_irq(serial_irq[i]), 115200,
+                        serial_hds[i]);
+        }
+    }
+
+    for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
+        if (parallel_hds[i]) {
+            parallel_init(parallel_io[i], isa_reserve_irq(parallel_irq[i]),
+                          parallel_hds[i]);
+        }
+    }
+
+    *isa_dev = isa_create_simple("i8042");
+    DMA_init(0);
+
+    for(i = 0; i < MAX_FD; i++) {
+        dinfo = drive_get(IF_FLOPPY, 0, i);
+        fd[i] = dinfo ? dinfo->bdrv : NULL;
+    }
+    *floppy_controller = fdctrl_init_isa(fd);
+}
+
 /* PC hardware initialisation */
 static void pc_init1(ram_addr_t ram_size,
                      const char *boot_device,
@@ -1328,12 +1380,9 @@ static void pc_init1(ram_addr_t ram_size,
     qemu_irq *isa_irq;
     qemu_irq *i8259;
     IsaIrqState *isa_irq_state;
-    DriveInfo *dinfo;
     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
-    BlockDriverState *fd[MAX_FD];
     fdctrl_t *floppy_controller;
     RTCState *rtc_state;
-    PITState *pit;
 
     pc_cpus_init(cpu_model);
 
@@ -1359,43 +1408,13 @@ static void pc_init1(ram_addr_t ram_size,
 
     pc_register_ferr_irq(isa_reserve_irq(13));
 
-    /* init basic PC hardware */
-    register_ioport_write(0x80, 1, 1, ioport80_write, NULL);
-
-    register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
-
     pc_vga_init(pci_enabled? pci_bus: NULL);
 
-    rtc_state = rtc_init(2000);
-    cmos_set_s3_resume_init(rtc_state);
-
-    qemu_register_boot_set(pc_boot_set, rtc_state);
-
-    register_ioport_read(0x92, 1, 1, ioport92_read, NULL);
-    register_ioport_write(0x92, 1, 1, ioport92_write, NULL);
-
+    /* init basic PC hardware */
+    pc_basic_device_init(isa_irq, &isa_dev, &floppy_controller, &rtc_state);
     if (pci_enabled) {
         isa_irq_state->ioapic = ioapic_init();
     }
-    pit = pit_init(0x40, isa_reserve_irq(0));
-    pcspk_init(pit);
-    if (!no_hpet) {
-        hpet_init(isa_irq);
-    }
-
-    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
-        if (serial_hds[i]) {
-            serial_init(serial_io[i], isa_reserve_irq(serial_irq[i]), 115200,
-                        serial_hds[i]);
-        }
-    }
-
-    for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
-        if (parallel_hds[i]) {
-            parallel_init(parallel_io[i], isa_reserve_irq(parallel_irq[i]),
-                          parallel_hds[i]);
-        }
-    }
 
     for(i = 0; i < nb_nics; i++) {
         NICInfo *nd = &nd_table[i];
@@ -1426,18 +1445,10 @@ static void pc_init1(ram_addr_t ram_size,
         }
     }
 
-    isa_dev = isa_create_simple("i8042");
-    DMA_init(0);
 #ifdef HAS_AUDIO
     audio_init(pci_enabled ? pci_bus : NULL, isa_irq);
 #endif
 
-    for(i = 0; i < MAX_FD; i++) {
-        dinfo = drive_get(IF_FLOPPY, 0, i);
-        fd[i] = dinfo ? dinfo->bdrv : NULL;
-    }
-    floppy_controller = fdctrl_init_isa(fd);
-
     cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd,
               floppy_controller, rtc_state);
 
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 17/61] pc: split out pci device init from pc_init1() into pc_pci_device_init()
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (15 preceding siblings ...)
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 16/61] pc: split out basic device init from pc_init1() into pc_basic_device_init() Isaku Yamahata
@ 2009-09-30 10:17 ` Isaku Yamahata
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 18/61] pc: split out piix specific part from pc.c into pc_piix.c Isaku Yamahata
                   ` (47 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:17 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

Split out pci device initialization from pc_init1() into pc_pci_device_init().
and removed unnecessary braces.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pc.c |   35 +++++++++++++++++++----------------
 1 files changed, 19 insertions(+), 16 deletions(-)

diff --git a/hw/pc.c b/hw/pc.c
index 380a66f..a304903 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1361,6 +1361,24 @@ static void pc_basic_device_init(qemu_irq *isa_irq,
     *floppy_controller = fdctrl_init_isa(fd);
 }
 
+static void pc_pci_device_init(PCIBus *pci_bus)
+{
+    int i;
+    int max_bus;
+
+    max_bus = drive_get_max_bus(IF_SCSI);
+    for (i = 0; i <= max_bus; i++) {
+        pci_create_simple(pci_bus, -1, "lsi53c895a");
+    }
+
+    /* Add virtio console devices */
+    for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) {
+        if (virtcon_hds[i]) {
+            pci_create_simple(pci_bus, -1, "virtio-console-pci");
+        }
+    }
+}
+
 /* PC hardware initialisation */
 static void pc_init1(ram_addr_t ram_size,
                      const char *boot_device,
@@ -1477,22 +1495,7 @@ static void pc_init1(ram_addr_t ram_size,
     }
 
     if (pci_enabled) {
-	int max_bus;
-        int bus;
-
-        max_bus = drive_get_max_bus(IF_SCSI);
-	for (bus = 0; bus <= max_bus; bus++) {
-            pci_create_simple(pci_bus, -1, "lsi53c895a");
-        }
-    }
-
-    /* Add virtio console devices */
-    if (pci_enabled) {
-        for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) {
-            if (virtcon_hds[i]) {
-                pci_create_simple(pci_bus, -1, "virtio-console-pci");
-            }
-        }
+        pc_pci_device_init(pci_bus);
     }
 }
 
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 18/61] pc: split out piix specific part from pc.c into pc_piix.c
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (16 preceding siblings ...)
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 17/61] pc: split out pci device init from pc_init1() into pc_pci_device_init() Isaku Yamahata
@ 2009-09-30 10:17 ` Isaku Yamahata
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 19/61] pc_piix: initialize ioapic before use Isaku Yamahata
                   ` (46 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:17 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

Finally, we can safely split out the piix specific part from pc.c
into pc_piix.c.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 Makefile.target |    2 +-
 hw/pc.c         |  257 +++++-------------------------------------------------
 hw/pc.h         |   32 +++++++
 hw/pc_piix.c    |  243 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 300 insertions(+), 234 deletions(-)
 create mode 100644 hw/pc_piix.c

diff --git a/Makefile.target b/Makefile.target
index 9f02ff2..fba44b8 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -187,7 +187,7 @@ obj-i386-y += cirrus_vga.o apic.o ioapic.o parallel.o acpi.o piix_pci.o
 obj-i386-y += usb-uhci.o vmmouse.o vmport.o vmware_vga.o hpet.o
 obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
 obj-i386-y += ne2000-isa.o
-obj-i386-y += pc_smbus.o pc_apm.o acpi_piix4.o
+obj-i386-y += pc_smbus.o pc_apm.o acpi_piix4.o pc_piix.o
 
 # shared objects
 obj-ppc-y = ppc.o ide/core.o ide/qdev.o ide/isa.o ide/pci.o ide/macio.o
diff --git a/hw/pc.c b/hw/pc.c
index a304903..72067e7 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -59,8 +59,6 @@
 #define FW_CFG_SMBIOS_ENTRIES (FW_CFG_ARCH_LOCAL + 1)
 #define FW_CFG_IRQ0_OVERRIDE (FW_CFG_ARCH_LOCAL + 2)
 
-#define MAX_IDE_BUS 2
-
 typedef struct rom_reset_data {
     uint8_t *data;
     target_phys_addr_t addr;
@@ -85,12 +83,7 @@ static void option_rom_setup_reset(target_phys_addr_t addr, unsigned size)
     qemu_register_reset(option_rom_reset, rrd);
 }
 
-typedef struct isa_irq_state {
-    qemu_irq *i8259;
-    qemu_irq *ioapic;
-} IsaIrqState;
-
-static void isa_irq_handler(void *opaque, int n, int level)
+void isa_irq_handler(void *opaque, int n, int level)
 {
     IsaIrqState *isa = (IsaIrqState *)opaque;
 
@@ -279,9 +272,9 @@ static int pc_boot_set(void *opaque, const char *boot_device)
 }
 
 /* hd_table must contain 4 block drivers */
-static void cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
-                      const char *boot_device, DriveInfo **hd_table,
-                      fdctrl_t *floppy_controller, RTCState *s)
+void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
+                  const char *boot_device, DriveInfo **hd_table,
+                  fdctrl_t *floppy_controller, RTCState *s)
 {
     int nbds, bds[3] = { 0, };
     int val;
@@ -1026,10 +1019,6 @@ static void load_linux(void *fw_cfg,
     generate_bootsect(option_rom, gpr, seg, 0);
 }
 
-static const int ide_iobase[2] = { 0x1f0, 0x170 };
-static const int ide_iobase2[2] = { 0x3f6, 0x376 };
-static const int ide_irq[2] = { 14, 15 };
-
 #define NE2000_NB_MAX 6
 
 static const int ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360,
@@ -1043,7 +1032,7 @@ static const int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc };
 static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
 
 #ifdef HAS_AUDIO
-static void audio_init (PCIBus *pci_bus, qemu_irq *pic)
+void pc_audio_init (PCIBus *pci_bus, qemu_irq *pic)
 {
     struct soundhw *c;
 
@@ -1061,7 +1050,7 @@ static void audio_init (PCIBus *pci_bus, qemu_irq *pic)
 }
 #endif
 
-static void pc_init_ne2k_isa(NICInfo *nd)
+void pc_init_ne2k_isa(NICInfo *nd)
 {
     static int nb_ne2k = 0;
 
@@ -1125,7 +1114,7 @@ static CPUState *pc_new_cpu(const char *cpu_model)
     return env;
 }
 
-static void pc_cpus_init(const char *cpu_model)
+void pc_cpus_init(const char *cpu_model)
 {
     int i;
 
@@ -1143,17 +1132,12 @@ static void pc_cpus_init(const char *cpu_model)
     }
 }
 
-static qemu_irq *pc_allocate_cpu_irq(void)
-{
-    return qemu_allocate_irqs(pic_irq_request, NULL, 1);
-}
-
-static void pc_memory_init(ram_addr_t ram_size,
-                           const char *kernel_filename,
-                           const char *kernel_cmdline,
-                           const char *initrd_filename,
-                           ram_addr_t *below_4g_mem_size_p,
-                           ram_addr_t *above_4g_mem_size_p)
+void pc_memory_init(ram_addr_t ram_size,
+                    const char *kernel_filename,
+                    const char *kernel_cmdline,
+                    const char *initrd_filename,
+                    ram_addr_t *below_4g_mem_size_p,
+                    ram_addr_t *above_4g_mem_size_p)
 {
     char *filename;
     int ret, linux_boot, i;
@@ -1287,7 +1271,12 @@ static void pc_memory_init(ram_addr_t ram_size,
     }
 }
 
-static void pc_vga_init(PCIBus *pci_bus)
+qemu_irq *pc_allocate_cpu_irq(void)
+{
+    return qemu_allocate_irqs(pic_irq_request, NULL, 1);
+}
+
+void pc_vga_init(PCIBus *pci_bus)
 {
     if (cirrus_vga_enabled) {
         if (pci_bus) {
@@ -1309,10 +1298,10 @@ static void pc_vga_init(PCIBus *pci_bus)
     }
 }
 
-static void pc_basic_device_init(qemu_irq *isa_irq,
-                                 ISADevice **isa_dev,
-                                 fdctrl_t **floppy_controller,
-                                 RTCState **rtc_state)
+void pc_basic_device_init(qemu_irq *isa_irq,
+                          ISADevice **isa_dev,
+                          fdctrl_t **floppy_controller,
+                          RTCState **rtc_state)
 {
     int i;
     DriveInfo *dinfo;
@@ -1361,7 +1350,7 @@ static void pc_basic_device_init(qemu_irq *isa_irq,
     *floppy_controller = fdctrl_init_isa(fd);
 }
 
-static void pc_pci_device_init(PCIBus *pci_bus)
+void pc_pci_device_init(PCIBus *pci_bus)
 {
     int i;
     int max_bus;
@@ -1379,152 +1368,6 @@ static void pc_pci_device_init(PCIBus *pci_bus)
     }
 }
 
-/* PC hardware initialisation */
-static void pc_init1(ram_addr_t ram_size,
-                     const char *boot_device,
-                     const char *kernel_filename,
-                     const char *kernel_cmdline,
-                     const char *initrd_filename,
-                     const char *cpu_model,
-                     int pci_enabled)
-{
-    int i;
-    ram_addr_t below_4g_mem_size, above_4g_mem_size;
-    PCIBus *pci_bus;
-    ISADevice *isa_dev;
-    PCII440FXState *i440fx_state;
-    int piix3_devfn = -1;
-    qemu_irq *cpu_irq;
-    qemu_irq *isa_irq;
-    qemu_irq *i8259;
-    IsaIrqState *isa_irq_state;
-    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
-    fdctrl_t *floppy_controller;
-    RTCState *rtc_state;
-
-    pc_cpus_init(cpu_model);
-
-    vmport_init();
-
-    /* allocate ram and load rom/bios */
-    pc_memory_init(ram_size, kernel_filename, kernel_cmdline, initrd_filename,
-                   &below_4g_mem_size, &above_4g_mem_size);
-
-    cpu_irq = pc_allocate_cpu_irq();
-    i8259 = i8259_init(cpu_irq[0]);
-    isa_irq_state = qemu_mallocz(sizeof(*isa_irq_state));
-    isa_irq_state->i8259 = i8259;
-    isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24);
-
-    if (pci_enabled) {
-        pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq);
-    } else {
-        pci_bus = NULL;
-        isa_bus_new(NULL);
-    }
-    isa_bus_irqs(isa_irq);
-
-    pc_register_ferr_irq(isa_reserve_irq(13));
-
-    pc_vga_init(pci_enabled? pci_bus: NULL);
-
-    /* init basic PC hardware */
-    pc_basic_device_init(isa_irq, &isa_dev, &floppy_controller, &rtc_state);
-    if (pci_enabled) {
-        isa_irq_state->ioapic = ioapic_init();
-    }
-
-    for(i = 0; i < nb_nics; i++) {
-        NICInfo *nd = &nd_table[i];
-
-        if (!pci_enabled || (nd->model && strcmp(nd->model, "ne2k_isa") == 0))
-            pc_init_ne2k_isa(nd);
-        else
-            pci_nic_init(nd, "e1000", NULL);
-    }
-
-    piix4_acpi_system_hot_add_init();
-
-    if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
-        fprintf(stderr, "qemu: too many IDE bus\n");
-        exit(1);
-    }
-
-    for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
-        hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
-    }
-
-    if (pci_enabled) {
-        pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1);
-    } else {
-        for(i = 0; i < MAX_IDE_BUS; i++) {
-            isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
-	                 hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
-        }
-    }
-
-#ifdef HAS_AUDIO
-    audio_init(pci_enabled ? pci_bus : NULL, isa_irq);
-#endif
-
-    cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd,
-              floppy_controller, rtc_state);
-
-    if (pci_enabled && usb_enabled) {
-        usb_uhci_piix3_init(pci_bus, piix3_devfn + 2);
-    }
-
-    if (pci_enabled && acpi_enabled) {
-        uint8_t *eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
-        i2c_bus *smbus;
-
-        /* TODO: Populate SPD eeprom data.  */
-        smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
-                              isa_reserve_irq(9));
-        for (i = 0; i < 8; i++) {
-            DeviceState *eeprom;
-            eeprom = qdev_create((BusState *)smbus, "smbus-eeprom");
-            qdev_prop_set_uint32(eeprom, "address", 0x50 + i);
-            qdev_prop_set_ptr(eeprom, "data", eeprom_buf + (i * 256));
-            qdev_init(eeprom);
-        }
-    }
-
-    if (i440fx_state) {
-        i440fx_init_memory_mappings(i440fx_state);
-    }
-
-    if (pci_enabled) {
-        pc_pci_device_init(pci_bus);
-    }
-}
-
-static void pc_init_pci(ram_addr_t ram_size,
-                        const char *boot_device,
-                        const char *kernel_filename,
-                        const char *kernel_cmdline,
-                        const char *initrd_filename,
-                        const char *cpu_model)
-{
-    pc_init1(ram_size, boot_device,
-             kernel_filename, kernel_cmdline,
-             initrd_filename, cpu_model, 1);
-}
-
-static void pc_init_isa(ram_addr_t ram_size,
-                        const char *boot_device,
-                        const char *kernel_filename,
-                        const char *kernel_cmdline,
-                        const char *initrd_filename,
-                        const char *cpu_model)
-{
-    if (cpu_model == NULL)
-        cpu_model = "486";
-    pc_init1(ram_size, boot_device,
-             kernel_filename, kernel_cmdline,
-             initrd_filename, cpu_model, 0);
-}
-
 /* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE)
    BIOS will read it and start S3 resume at POST Entry */
 static RTCState *rtc_state;
@@ -1540,55 +1383,3 @@ void cmos_set_s3_resume(void)
         rtc_set_memory(rtc_state, 0xF, 0xFE);
 #endif
 }
-
-static QEMUMachine pc_machine = {
-    .name = "pc-0.11",
-    .alias = "pc",
-    .desc = "Standard PC",
-    .init = pc_init_pci,
-    .max_cpus = 255,
-    .is_default = 1,
-};
-
-static QEMUMachine pc_machine_v0_10 = {
-    .name = "pc-0.10",
-    .desc = "Standard PC, qemu 0.10",
-    .init = pc_init_pci,
-    .max_cpus = 255,
-    .compat_props = (CompatProperty[]) {
-        {
-            .driver   = "virtio-blk-pci",
-            .property = "class",
-            .value    = stringify(PCI_CLASS_STORAGE_OTHER),
-        },{
-            .driver   = "virtio-console-pci",
-            .property = "class",
-            .value    = stringify(PCI_CLASS_DISPLAY_OTHER),
-        },{
-            .driver   = "virtio-net-pci",
-            .property = "vectors",
-            .value    = stringify(0),
-        },{
-            .driver   = "virtio-blk-pci",
-            .property = "vectors",
-            .value    = stringify(0),
-        },
-        { /* end of list */ }
-    },
-};
-
-static QEMUMachine isapc_machine = {
-    .name = "isapc",
-    .desc = "ISA-only PC",
-    .init = pc_init_isa,
-    .max_cpus = 1,
-};
-
-static void pc_machine_init(void)
-{
-    qemu_register_machine(&pc_machine);
-    qemu_register_machine(&pc_machine_v0_10);
-    qemu_register_machine(&isapc_machine);
-}
-
-machine_init(pc_machine_init);
diff --git a/hw/pc.h b/hw/pc.h
index 90acd75..dcb62a4 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -2,6 +2,7 @@
 #define HW_PC_H
 
 #include "qemu-common.h"
+#include "isa.h"
 
 /* PC-style peripherals (also used by other machines).  */
 
@@ -32,6 +33,14 @@ uint32_t pic_intack_read(PicState2 *s);
 void pic_info(Monitor *mon);
 void irq_info(Monitor *mon);
 
+/* ISA */
+typedef struct isa_irq_state {
+    qemu_irq *i8259;
+    qemu_irq *ioapic;
+} IsaIrqState;
+
+void isa_irq_handler(void *opaque, int n, int level);
+
 /* APIC */
 typedef struct IOAPICState IOAPICState;
 void apic_deliver_irq(uint8_t dest, uint8_t dest_mode,
@@ -94,6 +103,29 @@ extern int fd_bootchk;
 
 void pc_register_ferr_irq(qemu_irq irq);
 
+void pc_cpus_init(const char *cpu_model);
+void pc_memory_init(ram_addr_t ram_size,
+                    const char *kernel_filename,
+                    const char *kernel_cmdline,
+                    const char *initrd_filename,
+                    ram_addr_t *below_4g_mem_size_p,
+                    ram_addr_t *above_4g_mem_size_p);
+qemu_irq *pc_allocate_cpu_irq(void);
+void pc_vga_init(PCIBus *pci_bus);
+struct fdctrl_t;
+void pc_basic_device_init(qemu_irq *isa_irq,
+                          ISADevice **isa_dev,
+                          struct fdctrl_t **floppy_controller,
+                          RTCState **rtc_state);
+void pc_init_ne2k_isa(NICInfo *nd);
+#ifdef HAS_AUDIO
+void pc_audio_init (PCIBus *pci_bus, qemu_irq *pic);
+#endif
+void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
+                  const char *boot_device, DriveInfo **hd_table,
+                  struct fdctrl_t *floppy_controller, RTCState *s);
+void pc_pci_device_init(PCIBus *pci_bus);
+
 void ioport_set_a20(int enable);
 int ioport_get_a20(void);
 
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
new file mode 100644
index 0000000..276fd40
--- /dev/null
+++ b/hw/pc_piix.c
@@ -0,0 +1,243 @@
+/*
+ * QEMU PC System Emulator
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw.h"
+#include "pc.h"
+#include "fdc.h"
+#include "pci.h"
+#include "block.h"
+#include "sysemu.h"
+#include "audio/audio.h"
+#include "net.h"
+#include "smbus.h"
+#include "boards.h"
+#include "monitor.h"
+#include "fw_cfg.h"
+#include "hpet_emul.h"
+#include "smbios.h"
+#include "ide.h"
+
+#define MAX_IDE_BUS 2
+
+static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 };
+static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 };
+static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
+
+/* PC hardware initialisation */
+static void pc_init1(ram_addr_t ram_size,
+                     const char *boot_device,
+                     const char *kernel_filename,
+                     const char *kernel_cmdline,
+                     const char *initrd_filename,
+                     const char *cpu_model,
+                     int pci_enabled)
+{
+    int i;
+    ram_addr_t below_4g_mem_size, above_4g_mem_size;
+    PCIBus *pci_bus;
+    ISADevice *isa_dev;
+    PCII440FXState *i440fx_state;
+    int piix3_devfn = -1;
+    qemu_irq *cpu_irq;
+    qemu_irq *isa_irq;
+    qemu_irq *i8259;
+    IsaIrqState *isa_irq_state;
+    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
+    fdctrl_t *floppy_controller;
+    RTCState *rtc_state;
+
+    pc_cpus_init(cpu_model);
+
+    vmport_init();
+
+    /* allocate ram and load rom/bios */
+    pc_memory_init(ram_size, kernel_filename, kernel_cmdline, initrd_filename,
+                   &below_4g_mem_size, &above_4g_mem_size);
+
+    cpu_irq = pc_allocate_cpu_irq();
+    i8259 = i8259_init(cpu_irq[0]);
+    isa_irq_state = qemu_mallocz(sizeof(*isa_irq_state));
+    isa_irq_state->i8259 = i8259;
+    isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24);
+
+    if (pci_enabled) {
+        pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq);
+    } else {
+        pci_bus = NULL;
+        isa_bus_new(NULL);
+    }
+    isa_bus_irqs(isa_irq);
+
+    pc_register_ferr_irq(isa_reserve_irq(13));
+
+    pc_vga_init(pci_enabled? pci_bus: NULL);
+
+    /* init basic PC hardware */
+    pc_basic_device_init(isa_irq, &isa_dev, &floppy_controller, &rtc_state);
+    if (pci_enabled) {
+        isa_irq_state->ioapic = ioapic_init();
+    }
+
+    for(i = 0; i < nb_nics; i++) {
+        NICInfo *nd = &nd_table[i];
+
+        if (!pci_enabled || (nd->model && strcmp(nd->model, "ne2k_isa") == 0))
+            pc_init_ne2k_isa(nd);
+        else
+            pci_nic_init(nd, "e1000", NULL);
+    }
+
+    piix4_acpi_system_hot_add_init();
+
+    if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
+        fprintf(stderr, "qemu: too many IDE bus\n");
+        exit(1);
+    }
+
+    for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
+        hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
+    }
+
+    if (pci_enabled) {
+        pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1);
+    } else {
+        for(i = 0; i < MAX_IDE_BUS; i++) {
+            isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
+	                 hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
+        }
+    }
+
+#ifdef HAS_AUDIO
+    pc_audio_init(pci_enabled ? pci_bus : NULL, isa_irq);
+#endif
+
+    pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd,
+                 floppy_controller, rtc_state);
+
+    if (pci_enabled && usb_enabled) {
+        usb_uhci_piix3_init(pci_bus, piix3_devfn + 2);
+    }
+
+    if (pci_enabled && acpi_enabled) {
+        uint8_t *eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
+        i2c_bus *smbus;
+
+        /* TODO: Populate SPD eeprom data.  */
+        smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
+                              isa_reserve_irq(9));
+        for (i = 0; i < 8; i++) {
+            DeviceState *eeprom;
+            eeprom = qdev_create((BusState *)smbus, "smbus-eeprom");
+            qdev_prop_set_uint32(eeprom, "address", 0x50 + i);
+            qdev_prop_set_ptr(eeprom, "data", eeprom_buf + (i * 256));
+            qdev_init(eeprom);
+        }
+    }
+
+    if (i440fx_state) {
+        i440fx_init_memory_mappings(i440fx_state);
+    }
+
+    if (pci_enabled) {
+        pc_pci_device_init(pci_bus);
+    }
+}
+
+static void pc_init_pci(ram_addr_t ram_size,
+                        const char *boot_device,
+                        const char *kernel_filename,
+                        const char *kernel_cmdline,
+                        const char *initrd_filename,
+                        const char *cpu_model)
+{
+    pc_init1(ram_size, boot_device,
+             kernel_filename, kernel_cmdline,
+             initrd_filename, cpu_model, 1);
+}
+
+static void pc_init_isa(ram_addr_t ram_size,
+                        const char *boot_device,
+                        const char *kernel_filename,
+                        const char *kernel_cmdline,
+                        const char *initrd_filename,
+                        const char *cpu_model)
+{
+    if (cpu_model == NULL)
+        cpu_model = "486";
+    pc_init1(ram_size, boot_device,
+             kernel_filename, kernel_cmdline,
+             initrd_filename, cpu_model, 0);
+}
+
+static QEMUMachine pc_machine = {
+    .name = "pc-0.11",
+    .alias = "pc",
+    .desc = "Standard PC",
+    .init = pc_init_pci,
+    .max_cpus = 255,
+    .is_default = 1,
+};
+
+static QEMUMachine pc_machine_v0_10 = {
+    .name = "pc-0.10",
+    .desc = "Standard PC, qemu 0.10",
+    .init = pc_init_pci,
+    .max_cpus = 255,
+    .compat_props = (CompatProperty[]) {
+        {
+            .driver   = "virtio-blk-pci",
+            .property = "class",
+            .value    = stringify(PCI_CLASS_STORAGE_OTHER),
+        },{
+            .driver   = "virtio-console-pci",
+            .property = "class",
+            .value    = stringify(PCI_CLASS_DISPLAY_OTHER),
+        },{
+            .driver   = "virtio-net-pci",
+            .property = "vectors",
+            .value    = stringify(0),
+        },{
+            .driver   = "virtio-blk-pci",
+            .property = "vectors",
+            .value    = stringify(0),
+        },
+        { /* end of list */ }
+    },
+};
+
+static QEMUMachine isapc_machine = {
+    .name = "isapc",
+    .desc = "ISA-only PC",
+    .init = pc_init_isa,
+    .max_cpus = 1,
+};
+
+static void pc_machine_init(void)
+{
+    qemu_register_machine(&pc_machine);
+    qemu_register_machine(&pc_machine_v0_10);
+    qemu_register_machine(&isapc_machine);
+}
+
+machine_init(pc_machine_init);
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 19/61] pc_piix: initialize ioapic before use.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (17 preceding siblings ...)
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 18/61] pc: split out piix specific part from pc.c into pc_piix.c Isaku Yamahata
@ 2009-09-30 10:17 ` Isaku Yamahata
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 20/61] pci: fix PCI_DPRINTF() wrt variadic macro Isaku Yamahata
                   ` (45 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:17 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

initialize ioapic before use.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pc_piix.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 276fd40..4c8bb27 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -79,6 +79,9 @@ static void pc_init1(ram_addr_t ram_size,
     i8259 = i8259_init(cpu_irq[0]);
     isa_irq_state = qemu_mallocz(sizeof(*isa_irq_state));
     isa_irq_state->i8259 = i8259;
+    if (pci_enabled) {
+        isa_irq_state->ioapic = ioapic_init();
+    }
     isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24);
 
     if (pci_enabled) {
@@ -95,9 +98,6 @@ static void pc_init1(ram_addr_t ram_size,
 
     /* init basic PC hardware */
     pc_basic_device_init(isa_irq, &isa_dev, &floppy_controller, &rtc_state);
-    if (pci_enabled) {
-        isa_irq_state->ioapic = ioapic_init();
-    }
 
     for(i = 0; i < nb_nics; i++) {
         NICInfo *nd = &nd_table[i];
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 20/61] pci: fix PCI_DPRINTF() wrt variadic macro.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (18 preceding siblings ...)
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 19/61] pc_piix: initialize ioapic before use Isaku Yamahata
@ 2009-09-30 10:17 ` Isaku Yamahata
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 21/61] pci: introduce constant PCI_NUM_PINS for the number of interrupt pins, 4 Isaku Yamahata
                   ` (44 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:17 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

add missing ## in PCI_DPRINTF() to compile.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 64d70ed..4392574 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -29,7 +29,7 @@
 
 //#define DEBUG_PCI
 #ifdef DEBUG_PCI
-# define PCI_DPRINTF(format, ...)       printf(format, __VA_ARGS__)
+# define PCI_DPRINTF(format, ...)       printf(format, ## __VA_ARGS__)
 #else
 # define PCI_DPRINTF(format, ...)       do { } while (0)
 #endif
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 21/61] pci: introduce constant PCI_NUM_PINS for the number of interrupt pins, 4.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (19 preceding siblings ...)
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 20/61] pci: fix PCI_DPRINTF() wrt variadic macro Isaku Yamahata
@ 2009-09-30 10:17 ` Isaku Yamahata
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 22/61] pci: use appropriate PRIs in PCI_DPRINTF() Isaku Yamahata
                   ` (43 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:17 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

introduce constant PCI_NUM_PINS for the number of interrupt pins, 4.
and use it.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |    4 ++--
 hw/pci.h |    4 +++-
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 4392574..5c59092 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -177,7 +177,7 @@ const VMStateDescription vmstate_pci_device = {
         VMSTATE_INT32_LE(version_id, PCIDevice),
         VMSTATE_SINGLE(config, PCIDevice, 0, vmstate_info_pci_config,
                        typeof_field(PCIDevice,config)),
-        VMSTATE_INT32_ARRAY_V(irq_state, PCIDevice, 4, 2),
+        VMSTATE_INT32_ARRAY_V(irq_state, PCIDevice, PCI_NUM_PINS, 2),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -337,7 +337,7 @@ 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, 4);
+    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;
 }
diff --git a/hw/pci.h b/hw/pci.h
index caba5c8..aa3090e 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -156,6 +156,8 @@ typedef struct PCIIORegion {
 /* Size of the standard PCI config space */
 #define PCI_CONFIG_SPACE_SIZE 0x100
 
+#define PCI_NUM_PINS            4       /* A-D */
+
 /* Bits in cap_present field. */
 enum {
     QEMU_PCI_CAP_MSIX = 0x1,
@@ -191,7 +193,7 @@ struct PCIDevice {
     qemu_irq *irq;
 
     /* Current IRQ levels.  Used internally by the generic PCI code.  */
-    int irq_state[4];
+    int irq_state[PCI_NUM_PINS];
 
     /* Capability bits */
     uint32_t cap_present;
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 22/61] pci: use appropriate PRIs in PCI_DPRINTF().
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (20 preceding siblings ...)
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 21/61] pci: introduce constant PCI_NUM_PINS for the number of interrupt pins, 4 Isaku Yamahata
@ 2009-09-30 10:17 ` Isaku Yamahata
  2009-09-30 11:55   ` [Qemu-devel] " Michael S. Tsirkin
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 23/61] pci: use PCI_SLOT() and PCI_FUNC() Isaku Yamahata
                   ` (42 subsequent siblings)
  64 siblings, 1 reply; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:17 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

use appropriate PRIs in PCI_DPRINTF() for portability.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |   10 ++++++----
 1 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 5c59092..4a7568d 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -561,7 +561,7 @@ void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
     int config_addr, bus_num;
 
 #if 0
-    PCI_DPRINTF("pci_data_write: addr=%08x val=%08x len=%d\n",
+    PCI_DPRINTF("pci_data_write: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
                 addr, val, len);
 #endif
     bus_num = (addr >> 16) & 0xff;
@@ -573,7 +573,8 @@ void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
     if (!pci_dev)
         return;
     config_addr = addr & 0xff;
-    PCI_DPRINTF("pci_config_write: %s: addr=%02x val=%08x len=%d\n",
+    PCI_DPRINTF("pci_config_write: %s: "
+                "addr=%02"PRIx32" val=%08"PRI32x" len=%d\n",
                 pci_dev->name, config_addr, val, len);
     pci_dev->config_write(pci_dev, config_addr, val, len);
 }
@@ -609,11 +610,12 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
     }
     config_addr = addr & 0xff;
     val = pci_dev->config_read(pci_dev, config_addr, len);
-    PCI_DPRINTF("pci_config_read: %s: addr=%02x val=%08x len=%d\n",
+    PCI_DPRINTF("pci_config_read: %s: "
+                "addr=%02"PRIx32" val=%08"PRIx32" len=%d\n",
                 pci_dev->name, config_addr, val, len);
  the_end:
 #if 0
-    PCI_DPRINTF("pci_data_read: addr=%08x val=%08x len=%d\n",
+    PCI_DPRINTF("pci_data_read: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
                 addr, val, len);
 #endif
     return val;
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 23/61] pci: use PCI_SLOT() and PCI_FUNC().
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (21 preceding siblings ...)
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 22/61] pci: use appropriate PRIs in PCI_DPRINTF() Isaku Yamahata
@ 2009-09-30 10:17 ` Isaku Yamahata
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 24/61] pci: define a constant to represent a unmapped bar and use it Isaku Yamahata
                   ` (41 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:17 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

use PCI_SLOT() and PCI_FUNC() where appropriate instead of
direct use of bit operation.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 4a7568d..1bd92fc 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -703,7 +703,7 @@ static void pci_info_device(PCIDevice *d)
     const pci_class_desc *desc;
 
     monitor_printf(mon, "  Bus %2d, device %3d, function %d:\n",
-                   d->bus->bus_num, d->devfn >> 3, d->devfn & 7);
+                   d->bus->bus_num, PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
     class = le16_to_cpu(*((uint16_t *)(d->config + PCI_CLASS_DEVICE)));
     monitor_printf(mon, "    ");
     desc = pci_class_descriptions;
@@ -1039,7 +1039,7 @@ static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent)
     monitor_printf(mon, "%*sclass %s, addr %02x:%02x.%x, "
                    "pci id %04x:%04x (sub %04x:%04x)\n",
                    indent, "", ctxt,
-                   d->bus->bus_num, d->devfn >> 3, d->devfn & 7,
+                   d->bus->bus_num, PCI_SLOT(d->devfn), PCI_FUNC(d->devfn),
                    le16_to_cpu(*((uint16_t *)(d->config + PCI_VENDOR_ID))),
                    le16_to_cpu(*((uint16_t *)(d->config + PCI_DEVICE_ID))),
                    le16_to_cpu(*((uint16_t *)(d->config + PCI_SUBSYSTEM_VENDOR_ID))),
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 24/61] pci: define a constant to represent a unmapped bar and use it.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (22 preceding siblings ...)
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 23/61] pci: use PCI_SLOT() and PCI_FUNC() Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 25/61] pci: use uint64_t for bar addr and size instead of uint32_t Isaku Yamahata
                   ` (40 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

define a constant to represent a unmapped bar instead of -1 and use it.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/cirrus_vga.c |    2 +-
 hw/pci.c        |   18 +++++++++---------
 hw/pci.h        |    1 +
 3 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 7e95f10..fd2367a 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -3206,7 +3206,7 @@ static void pci_cirrus_write_config(PCIDevice *d,
     CirrusVGAState *s = &pvs->cirrus_vga;
 
     pci_default_write_config(d, address, val, len);
-    if (s->vga.map_addr && d->io_regions[0].addr == -1)
+    if (s->vga.map_addr && d->io_regions[0].addr == PCI_BAR_UNMAPPED)
         s->vga.map_addr = 0;
     cirrus_update_memory_access(s);
 }
diff --git a/hw/pci.c b/hw/pci.c
index 1bd92fc..bd86a11 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -366,7 +366,7 @@ static void pci_unregister_io_regions(PCIDevice *pci_dev)
 
     for(i = 0; i < PCI_NUM_REGIONS; i++) {
         r = &pci_dev->io_regions[i];
-        if (!r->size || r->addr == -1)
+        if (!r->size || r->addr == PCI_BAR_UNMAPPED)
             continue;
         if (r->type == PCI_ADDRESS_SPACE_IO) {
             isa_unassign_ioport(r->addr, r->size);
@@ -413,7 +413,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
     }
 
     r = &pci_dev->io_regions[region_num];
-    r->addr = -1;
+    r->addr = PCI_BAR_UNMAPPED;
     r->size = size;
     r->type = type;
     r->map_func = map_func;
@@ -455,10 +455,10 @@ static void pci_update_mappings(PCIDevice *d)
                     /* NOTE: we have only 64K ioports on PC */
                     if (last_addr <= new_addr || new_addr == 0 ||
                         last_addr >= 0x10000) {
-                        new_addr = -1;
+                        new_addr = PCI_BAR_UNMAPPED;
                     }
                 } else {
-                    new_addr = -1;
+                    new_addr = PCI_BAR_UNMAPPED;
                 }
             } else {
                 if (cmd & PCI_COMMAND_MEMORY) {
@@ -474,17 +474,17 @@ static void pci_update_mappings(PCIDevice *d)
                        mappings, we handle specific values as invalid
                        mappings. */
                     if (last_addr <= new_addr || new_addr == 0 ||
-                        last_addr == -1) {
-                        new_addr = -1;
+                        last_addr == PCI_BAR_UNMAPPED) {
+                        new_addr = PCI_BAR_UNMAPPED;
                     }
                 } else {
                 no_mem_map:
-                    new_addr = -1;
+                    new_addr = PCI_BAR_UNMAPPED;
                 }
             }
             /* now do the real mapping */
             if (new_addr != r->addr) {
-                if (r->addr != -1) {
+                if (r->addr != PCI_BAR_UNMAPPED) {
                     if (r->type & PCI_ADDRESS_SPACE_IO) {
                         int class;
                         /* NOTE: specific hack for IDE in PC case:
@@ -503,7 +503,7 @@ static void pci_update_mappings(PCIDevice *d)
                     }
                 }
                 r->addr = new_addr;
-                if (r->addr != -1) {
+                if (r->addr != PCI_BAR_UNMAPPED) {
                     r->map_func(d, i, r->addr, r->size, r->type);
                 }
             }
diff --git a/hw/pci.h b/hw/pci.h
index aa3090e..dd34c84 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -85,6 +85,7 @@ typedef int PCIUnregisterFunc(PCIDevice *pci_dev);
 
 typedef struct PCIIORegion {
     uint32_t addr; /* current PCI mapping address. -1 means not mapped */
+#define PCI_BAR_UNMAPPED        (~(uint32_t)0)
     uint32_t size;
     uint8_t type;
     PCIMapIORegionFunc *map_func;
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 25/61] pci: use uint64_t for bar addr and size instead of uint32_t.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (23 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 24/61] pci: define a constant to represent a unmapped bar and use it Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 14:55   ` malc
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 26/61] pci: 64bit bar support Isaku Yamahata
                   ` (39 subsequent siblings)
  64 siblings, 1 reply; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

This patch is preliminary for 64bit bar.
For 64bit bar support, replace uint32_t with uint64_t for addr/size
to be able to represent 64bit.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/ac97.c         |    2 +-
 hw/cirrus_vga.c   |    4 ++--
 hw/e1000.c        |   12 +++++++-----
 hw/eepro100.c     |   10 ++++++----
 hw/es1370.c       |    2 +-
 hw/ide/pci.c      |    4 ++--
 hw/lsi53c895a.c   |    6 +++---
 hw/macio.c        |    2 +-
 hw/msix.c         |    2 +-
 hw/msix.h         |    2 +-
 hw/ne2000.c       |    2 +-
 hw/openpic.c      |    2 +-
 hw/pci.c          |   24 +++++++++++++++---------
 hw/pci.h          |   10 +++++-----
 hw/pcnet.c        |    9 +++++----
 hw/rtl8139.c      |    4 ++--
 hw/sun4u.c        |    2 +-
 hw/usb-ohci.c     |    2 +-
 hw/usb-uhci.c     |    2 +-
 hw/vga-pci.c      |    2 +-
 hw/virtio-pci.c   |    2 +-
 hw/vmware_vga.c   |    4 ++--
 hw/wdt_i6300esb.c |    5 +++--
 23 files changed, 64 insertions(+), 52 deletions(-)

diff --git a/hw/ac97.c b/hw/ac97.c
index 610ca60..e9667a0 100644
--- a/hw/ac97.c
+++ b/hw/ac97.c
@@ -1250,7 +1250,7 @@ static int ac97_load (QEMUFile *f, void *opaque, int version_id)
 }
 
 static void ac97_map (PCIDevice *pci_dev, int region_num,
-                      uint32_t addr, uint32_t size, int type)
+                      uint64_t addr, uint64_t size, int type)
 {
     AC97LinkState *s = DO_UPCAST (AC97LinkState, dev, pci_dev);
     PCIDevice *d = &s->dev;
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index fd2367a..5103763 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -3170,7 +3170,7 @@ void isa_cirrus_vga_init(void)
  ***************************************/
 
 static void cirrus_pci_lfb_map(PCIDevice *d, int region_num,
-			       uint32_t addr, uint32_t size, int type)
+			       uint64_t addr, uint64_t size, int type)
 {
     CirrusVGAState *s = &DO_UPCAST(PCICirrusVGAState, dev, d)->cirrus_vga;
 
@@ -3191,7 +3191,7 @@ static void cirrus_pci_lfb_map(PCIDevice *d, int region_num,
 }
 
 static void cirrus_pci_mmio_map(PCIDevice *d, int region_num,
-				uint32_t addr, uint32_t size, int type)
+				uint64_t addr, uint64_t size, int type)
 {
     CirrusVGAState *s = &DO_UPCAST(PCICirrusVGAState, dev, d)->cirrus_vga;
 
diff --git a/hw/e1000.c b/hw/e1000.c
index 95c471c..616b590 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -142,10 +142,11 @@ static const char phy_regcap[0x20] = {
 };
 
 static void
-ioport_map(PCIDevice *pci_dev, int region_num, uint32_t addr,
-           uint32_t size, int type)
+ioport_map(PCIDevice *pci_dev, int region_num, uint64_t addr,
+           uint64_t size, int type)
 {
-    DBGOUT(IO, "e1000_ioport_map addr=0x%04x size=0x%08x\n", addr, size);
+    DBGOUT(IO, "e1000_ioport_map addr=0x%04"PRIx64" size=0x%08"PRIx64"\n",
+           addr, size);
 }
 
 static void
@@ -1030,7 +1031,7 @@ static CPUReadMemoryFunc * const e1000_mmio_read[] = {
 
 static void
 e1000_mmio_map(PCIDevice *pci_dev, int region_num,
-                uint32_t addr, uint32_t size, int type)
+                uint64_t addr, uint64_t size, int type)
 {
     E1000State *d = DO_UPCAST(E1000State, dev, pci_dev);
     int i;
@@ -1040,7 +1041,8 @@ e1000_mmio_map(PCIDevice *pci_dev, int region_num,
     };
 
 
-    DBGOUT(MMIO, "e1000_mmio_map addr=0x%08x 0x%08x\n", addr, size);
+    DBGOUT(MMIO, "e1000_mmio_map addr=0x%08"PRIx64" 0x%08"PRIx64"\n",
+           addr, size);
 
     cpu_register_physical_memory(addr, PNPMMIO_SIZE, d->mmio_index);
     qemu_register_coalesced_mmio(addr, excluded_regs[0]);
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 3f84e26..062b590 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1374,11 +1374,12 @@ static void ioport_write4(void *opaque, uint32_t addr, uint32_t val)
 /* PCI EEPRO100 definitions */
 
 static void pci_map(PCIDevice * pci_dev, int region_num,
-                    uint32_t addr, uint32_t size, int type)
+                    uint64_t addr, uint64_t size, int type)
 {
     EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
 
-    TRACE(OTHER, logout("region %d, addr=0x%08x, size=0x%08x, type=%d\n",
+    TRACE(OTHER, logout("region %d, addr=0x%08"PRIx64", "
+          "size=0x%08"PRIx64", type=%d\n",
           region_num, addr, size, type));
 
     assert(region_num == 1);
@@ -1453,11 +1454,12 @@ static CPUReadMemoryFunc * const pci_mmio_read[] = {
 };
 
 static void pci_mmio_map(PCIDevice * pci_dev, int region_num,
-                         uint32_t addr, uint32_t size, int type)
+                         uint64_t addr, uint64_t size, int type)
 {
     EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
 
-    TRACE(OTHER, logout("region %d, addr=0x%08x, size=0x%08x, type=%d\n",
+    TRACE(OTHER, logout("region %d, addr=0x%08"PRIx64", "
+          "size=0x%08"PRIx64", type=%d\n",
           region_num, addr, size, type));
 
     if (region_num == 0) {
diff --git a/hw/es1370.c b/hw/es1370.c
index 9071a48..e4031f6 100644
--- a/hw/es1370.c
+++ b/hw/es1370.c
@@ -907,7 +907,7 @@ static void es1370_adc_callback (void *opaque, int avail)
 }
 
 static void es1370_map (PCIDevice *pci_dev, int region_num,
-                        uint32_t addr, uint32_t size, int type)
+                        uint64_t addr, uint64_t size, int type)
 {
     ES1370State *s = DO_UPCAST (ES1370State, dev, pci_dev);
 
diff --git a/hw/ide/pci.c b/hw/ide/pci.c
index 89ecd44..3514803 100644
--- a/hw/ide/pci.c
+++ b/hw/ide/pci.c
@@ -60,7 +60,7 @@ typedef struct PCIIDEState {
 static void cmd646_update_irq(PCIIDEState *d);
 
 static void ide_map(PCIDevice *pci_dev, int region_num,
-                    uint32_t addr, uint32_t size, int type)
+                    uint64_t addr, uint64_t size, int type)
 {
     PCIIDEState *d = (PCIIDEState *)pci_dev;
     IDEBus *bus;
@@ -245,7 +245,7 @@ static void bmdma_addr_writel(void *opaque, uint32_t addr, uint32_t val)
 }
 
 static void bmdma_map(PCIDevice *pci_dev, int region_num,
-                    uint32_t addr, uint32_t size, int type)
+                    uint64_t addr, uint64_t size, int type)
 {
     PCIIDEState *d = (PCIIDEState *)pci_dev;
     int i;
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 62bdca8..e443757 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -1926,7 +1926,7 @@ static void lsi_io_writel(void *opaque, uint32_t addr, uint32_t val)
 }
 
 static void lsi_io_mapfunc(PCIDevice *pci_dev, int region_num,
-                           uint32_t addr, uint32_t size, int type)
+                           uint64_t addr, uint64_t size, int type)
 {
     LSIState *s = DO_UPCAST(LSIState, dev, pci_dev);
 
@@ -1941,7 +1941,7 @@ static void lsi_io_mapfunc(PCIDevice *pci_dev, int region_num,
 }
 
 static void lsi_ram_mapfunc(PCIDevice *pci_dev, int region_num,
-                            uint32_t addr, uint32_t size, int type)
+                            uint64_t addr, uint64_t size, int type)
 {
     LSIState *s = DO_UPCAST(LSIState, dev, pci_dev);
 
@@ -1951,7 +1951,7 @@ static void lsi_ram_mapfunc(PCIDevice *pci_dev, int region_num,
 }
 
 static void lsi_mmio_mapfunc(PCIDevice *pci_dev, int region_num,
-                             uint32_t addr, uint32_t size, int type)
+                             uint64_t addr, uint64_t size, int type)
 {
     LSIState *s = DO_UPCAST(LSIState, dev, pci_dev);
 
diff --git a/hw/macio.c b/hw/macio.c
index 8cfadfc..41412c3 100644
--- a/hw/macio.c
+++ b/hw/macio.c
@@ -40,7 +40,7 @@ struct macio_state_t {
 };
 
 static void macio_map (PCIDevice *pci_dev, int region_num,
-                       uint32_t addr, uint32_t size, int type)
+                       uint64_t addr, uint64_t size, int type)
 {
     macio_state_t *macio_state;
     int i;
diff --git a/hw/msix.c b/hw/msix.c
index 3782994..1c5d63f 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -201,7 +201,7 @@ static CPUReadMemoryFunc * const msix_mmio_read[] = {
 
 /* Should be called from device's map method. */
 void msix_mmio_map(PCIDevice *d, int region_num,
-                   uint32_t addr, uint32_t size, int type)
+                   uint64_t addr, uint64_t size, int type)
 {
     uint8_t *config = d->config + d->msix_cap;
     uint32_t table = pci_get_long(config + MSIX_TABLE_OFFSET);
diff --git a/hw/msix.h b/hw/msix.h
index 9367ba3..c9eb176 100644
--- a/hw/msix.h
+++ b/hw/msix.h
@@ -11,7 +11,7 @@ void msix_write_config(PCIDevice *pci_dev, uint32_t address,
                        uint32_t val, int len);
 
 void msix_mmio_map(PCIDevice *pci_dev, int region_num,
-                   uint32_t addr, uint32_t size, int type);
+                   uint64_t addr, uint64_t size, int type);
 
 int msix_uninit(PCIDevice *d);
 
diff --git a/hw/ne2000.c b/hw/ne2000.c
index 87f1e59..f32e5bb 100644
--- a/hw/ne2000.c
+++ b/hw/ne2000.c
@@ -715,7 +715,7 @@ static int pci_ne2000_load(QEMUFile* f, void* opaque, int version_id)
 /* PCI NE2000 definitions */
 
 static void ne2000_map(PCIDevice *pci_dev, int region_num,
-                       uint32_t addr, uint32_t size, int type)
+                       uint64_t addr, uint64_t size, int type)
 {
     PCINE2000State *d = DO_UPCAST(PCINE2000State, dev, pci_dev);
     NE2000State *s = &d->ne2000;
diff --git a/hw/openpic.c b/hw/openpic.c
index 74dde6d..acee1bc 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -1026,7 +1026,7 @@ static CPUReadMemoryFunc * const openpic_read[] = {
 };
 
 static void openpic_map(PCIDevice *pci_dev, int region_num,
-                        uint32_t addr, uint32_t size, int type)
+                        uint64_t addr, uint64_t size, int type)
 {
     openpic_t *opp;
 
diff --git a/hw/pci.c b/hw/pci.c
index bd86a11..1b156be 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -396,19 +396,19 @@ int pci_unregister_device(PCIDevice *pci_dev)
 }
 
 void pci_register_bar(PCIDevice *pci_dev, int region_num,
-                            uint32_t size, int type,
+                            uint64_t size, int type,
                             PCIMapIORegionFunc *map_func)
 {
     PCIIORegion *r;
     uint32_t addr;
-    uint32_t wmask;
+    uint64_t wmask;
 
     if ((unsigned int)region_num >= PCI_NUM_REGIONS)
         return;
 
     if (size & (size-1)) {
         fprintf(stderr, "ERROR: PCI region size must be pow2 "
-                    "type=0x%x, size=0x%x\n", type, size);
+                    "type=0x%x, size=0x%"PRIx64"\n", type, size);
         exit(1);
     }
 
@@ -427,7 +427,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
         addr = 0x10 + region_num * 4;
     }
     *(uint32_t *)(pci_dev->config + addr) = cpu_to_le32(type);
-    *(uint32_t *)(pci_dev->wmask + addr) = cpu_to_le32(wmask);
+    *(uint32_t *)(pci_dev->wmask + addr) = cpu_to_le32(wmask & 0xffffffff);
     *(uint32_t *)(pci_dev->cmask + addr) = 0xffffffff;
 }
 
@@ -435,7 +435,8 @@ static void pci_update_mappings(PCIDevice *d)
 {
     PCIIORegion *r;
     int cmd, i;
-    uint32_t last_addr, new_addr, config_ofs;
+    uint64_t last_addr, new_addr;
+    uint32_t config_ofs;
 
     cmd = le16_to_cpu(*(uint16_t *)(d->config + PCI_COMMAND));
     for(i = 0; i < PCI_NUM_REGIONS; i++) {
@@ -474,7 +475,11 @@ static void pci_update_mappings(PCIDevice *d)
                        mappings, we handle specific values as invalid
                        mappings. */
                     if (last_addr <= new_addr || new_addr == 0 ||
-                        last_addr == PCI_BAR_UNMAPPED) {
+                        last_addr == PCI_BAR_UNMAPPED ||
+
+                        /* keep old behaviour
+                         * without this, PC ide doesn't work well. */
+                        last_addr >= UINT32_MAX) {
                         new_addr = PCI_BAR_UNMAPPED;
                     }
                 } else {
@@ -730,10 +735,10 @@ static void pci_info_device(PCIDevice *d)
         if (r->size != 0) {
             monitor_printf(mon, "      BAR%d: ", i);
             if (r->type & PCI_ADDRESS_SPACE_IO) {
-                monitor_printf(mon, "I/O at 0x%04x [0x%04x].\n",
+                monitor_printf(mon, "I/O at 0x%04"PRIx64" [0x%04"PRIx64"].\n",
                                r->addr, r->addr + r->size - 1);
             } else {
-                monitor_printf(mon, "32 bit memory at 0x%08x [0x%08x].\n",
+                monitor_printf(mon, "32 bit memory at 0x%08"PRIx64" [0x%08"PRIx64"].\n",
                                r->addr, r->addr + r->size - 1);
             }
         }
@@ -1048,7 +1053,8 @@ static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent)
         r = &d->io_regions[i];
         if (!r->size)
             continue;
-        monitor_printf(mon, "%*sbar %d: %s at 0x%x [0x%x]\n", indent, "",
+        monitor_printf(mon, "%*sbar %d: %s at 0x%"PRIx64" [0x%"PRIx64"]\n",
+                       indent, "",
                        i, r->type & PCI_ADDRESS_SPACE_IO ? "i/o" : "mem",
                        r->addr, r->addr + r->size - 1);
     }
diff --git a/hw/pci.h b/hw/pci.h
index dd34c84..72a78af 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -76,7 +76,7 @@ typedef void PCIConfigWriteFunc(PCIDevice *pci_dev,
 typedef uint32_t PCIConfigReadFunc(PCIDevice *pci_dev,
                                    uint32_t address, int len);
 typedef void PCIMapIORegionFunc(PCIDevice *pci_dev, int region_num,
-                                uint32_t addr, uint32_t size, int type);
+                                uint64_t addr, uint64_t size, int type);
 typedef int PCIUnregisterFunc(PCIDevice *pci_dev);
 
 #define PCI_ADDRESS_SPACE_MEM		0x00
@@ -84,9 +84,9 @@ typedef int PCIUnregisterFunc(PCIDevice *pci_dev);
 #define PCI_ADDRESS_SPACE_MEM_PREFETCH	0x08
 
 typedef struct PCIIORegion {
-    uint32_t addr; /* current PCI mapping address. -1 means not mapped */
-#define PCI_BAR_UNMAPPED        (~(uint32_t)0)
-    uint32_t size;
+    uint64_t addr; /* current PCI mapping address. -1 means not mapped */
+#define PCI_BAR_UNMAPPED        (~(uint64_t)0)
+    uint64_t size;
     uint8_t type;
     PCIMapIORegionFunc *map_func;
 } PCIIORegion;
@@ -230,7 +230,7 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name,
 int pci_unregister_device(PCIDevice *pci_dev);
 
 void pci_register_bar(PCIDevice *pci_dev, int region_num,
-                            uint32_t size, int type,
+                            uint64_t size, int type,
                             PCIMapIORegionFunc *map_func);
 
 int pci_add_capability(PCIDevice *pci_dev, uint8_t cap_id, uint8_t cap_size);
diff --git a/hw/pcnet.c b/hw/pcnet.c
index ae98a20..3eaecb1 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -1761,12 +1761,13 @@ static uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr)
 }
 
 static void pcnet_ioport_map(PCIDevice *pci_dev, int region_num,
-                             uint32_t addr, uint32_t size, int type)
+                             uint64_t addr, uint64_t size, int type)
 {
     PCNetState *d = &DO_UPCAST(PCIPCNetState, pci_dev, pci_dev)->state;
 
 #ifdef PCNET_DEBUG_IO
-    printf("pcnet_ioport_map addr=0x%04x size=0x%04x\n", addr, size);
+    printf("pcnet_ioport_map addr=0x%04"PRIx64" size=0x%04"PRIx64"\n",
+           addr, size);
 #endif
 
     register_ioport_write(addr, 16, 1, pcnet_aprom_writeb, d);
@@ -1989,12 +1990,12 @@ static CPUReadMemoryFunc * const pcnet_mmio_read[] = {
 };
 
 static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num,
-                            uint32_t addr, uint32_t size, int type)
+                            uint64_t addr, uint64_t size, int type)
 {
     PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, pci_dev);
 
 #ifdef PCNET_DEBUG_IO
-    printf("pcnet_mmio_map addr=0x%08x 0x%08x\n", addr, size);
+    printf("pcnet_mmio_map addr=0x%08"PRIx64" 0x%08"PRIx64"\n", addr, size);
 #endif
 
     cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->state.mmio_index);
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 83cb1ff..c207c39 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -3324,7 +3324,7 @@ static int rtl8139_load(QEMUFile* f,void* opaque,int version_id)
 /* PCI RTL8139 definitions */
 
 static void rtl8139_mmio_map(PCIDevice *pci_dev, int region_num,
-                       uint32_t addr, uint32_t size, int type)
+                       uint64_t addr, uint64_t size, int type)
 {
     RTL8139State *s = DO_UPCAST(RTL8139State, dev, pci_dev);
 
@@ -3332,7 +3332,7 @@ static void rtl8139_mmio_map(PCIDevice *pci_dev, int region_num,
 }
 
 static void rtl8139_ioport_map(PCIDevice *pci_dev, int region_num,
-                       uint32_t addr, uint32_t size, int type)
+                       uint64_t addr, uint64_t size, int type)
 {
     RTL8139State *s = DO_UPCAST(RTL8139State, dev, pci_dev);
 
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 2c97d9d..348e750 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -344,7 +344,7 @@ static const int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc };
 static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
 
 static void ebus_mmio_mapfunc(PCIDevice *pci_dev, int region_num,
-                              uint32_t addr, uint32_t size, int type)
+                              uint64_t addr, uint64_t size, int type)
 {
     DPRINTF("Mapping region %d registers at %08x\n", region_num, addr);
     switch (region_num) {
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 6e428c4..9757d0f 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -1707,7 +1707,7 @@ typedef struct {
 } OHCIPCIState;
 
 static void ohci_mapfunc(PCIDevice *pci_dev, int i,
-            uint32_t addr, uint32_t size, int type)
+            uint64_t addr, uint64_t size, int type)
 {
     OHCIPCIState *ohci = DO_UPCAST(OHCIPCIState, pci_dev, pci_dev);
     cpu_register_physical_memory(addr, size, ohci->state.mem);
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 6807413..afa922d 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -1059,7 +1059,7 @@ static void uhci_frame_timer(void *opaque)
 }
 
 static void uhci_map(PCIDevice *pci_dev, int region_num,
-                    uint32_t addr, uint32_t size, int type)
+                    uint64_t addr, uint64_t size, int type)
 {
     UHCIState *s = (UHCIState *)pci_dev;
 
diff --git a/hw/vga-pci.c b/hw/vga-pci.c
index 6038cec..3ff353d 100644
--- a/hw/vga-pci.c
+++ b/hw/vga-pci.c
@@ -71,7 +71,7 @@ void vga_dirty_log_start(VGACommonState *s)
 }
 
 static void vga_map(PCIDevice *pci_dev, int region_num,
-                    uint32_t addr, uint32_t size, int type)
+                    uint64_t addr, uint64_t size, int type)
 {
     PCIVGAState *d = (PCIVGAState *)pci_dev;
     VGACommonState *s = &d->vga;
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index bd5a7c4..0e7a71d 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -342,7 +342,7 @@ static void virtio_pci_config_writel(void *opaque, uint32_t addr, uint32_t val)
 }
 
 static void virtio_map(PCIDevice *pci_dev, int region_num,
-                       uint32_t addr, uint32_t size, int type)
+                       uint64_t addr, uint64_t size, int type)
 {
     VirtIOPCIProxy *proxy = container_of(pci_dev, VirtIOPCIProxy, pci_dev);
     VirtIODevice *vdev = proxy->vdev;
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index a273f35..ffb3ec6 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1174,7 +1174,7 @@ static int pci_vmsvga_load(QEMUFile *f, void *opaque, int version_id)
 }
 
 static void pci_vmsvga_map_ioport(PCIDevice *pci_dev, int region_num,
-                uint32_t addr, uint32_t size, int type)
+                uint64_t addr, uint64_t size, int type)
 {
     struct pci_vmsvga_state_s *d = (struct pci_vmsvga_state_s *) pci_dev;
     struct vmsvga_state_s *s = &d->chip;
@@ -1194,7 +1194,7 @@ static void pci_vmsvga_map_ioport(PCIDevice *pci_dev, int region_num,
 }
 
 static void pci_vmsvga_map_mem(PCIDevice *pci_dev, int region_num,
-                uint32_t addr, uint32_t size, int type)
+                uint64_t addr, uint64_t size, int type)
 {
     struct pci_vmsvga_state_s *d = (struct pci_vmsvga_state_s *) pci_dev;
     struct vmsvga_state_s *s = &d->chip;
diff --git a/hw/wdt_i6300esb.c b/hw/wdt_i6300esb.c
index 3abaa87..0660338 100644
--- a/hw/wdt_i6300esb.c
+++ b/hw/wdt_i6300esb.c
@@ -347,7 +347,7 @@ static void i6300esb_mem_writel(void *vp, target_phys_addr_t addr, uint32_t val)
 }
 
 static void i6300esb_map(PCIDevice *dev, int region_num,
-                         uint32_t addr, uint32_t size, int type)
+                         uint64_t addr, uint64_t size, int type)
 {
     static CPUReadMemoryFunc * const mem_read[3] = {
         i6300esb_mem_readb,
@@ -362,7 +362,8 @@ static void i6300esb_map(PCIDevice *dev, int region_num,
     I6300State *d = DO_UPCAST(I6300State, dev, dev);
     int io_mem;
 
-    i6300esb_debug("addr = %x, size = %x, type = %d\n", addr, size, type);
+    i6300esb_debug("addr = %"PRIx64", size = %"PRIx64", type = %d\n",
+                   addr, size, type);
 
     io_mem = cpu_register_io_memory(mem_read, mem_write, d);
     cpu_register_physical_memory (addr, 0x10, io_mem);
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 26/61] pci: 64bit bar support.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (24 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 25/61] pci: use uint64_t for bar addr and size instead of uint32_t Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 27/61] pci: clean up of pci_update_mappings() Isaku Yamahata
                   ` (38 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

implemented pci 64bit bar support.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |   46 ++++++++++++++++++++++++++++++++++++++++------
 hw/pci.h |    9 +++++++++
 2 files changed, 49 insertions(+), 6 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 1b156be..beda5ef 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -426,9 +426,15 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
     } else {
         addr = 0x10 + region_num * 4;
     }
+
     *(uint32_t *)(pci_dev->config + addr) = cpu_to_le32(type);
-    *(uint32_t *)(pci_dev->wmask + addr) = cpu_to_le32(wmask & 0xffffffff);
-    *(uint32_t *)(pci_dev->cmask + addr) = 0xffffffff;
+    if (pci_bar_is_64bit(r)) {
+        *(uint64_t *)(pci_dev->wmask + addr) = cpu_to_le64(wmask);
+        *(uint64_t *)(pci_dev->cmask + addr) = ~0ULL;
+    } else {
+        *(uint32_t *)(pci_dev->wmask + addr) = cpu_to_le32(wmask & 0xffffffff);
+        *(uint32_t *)(pci_dev->cmask + addr) = 0xffffffff;
+    }
 }
 
 static void pci_update_mappings(PCIDevice *d)
@@ -463,8 +469,14 @@ static void pci_update_mappings(PCIDevice *d)
                 }
             } else {
                 if (cmd & PCI_COMMAND_MEMORY) {
-                    new_addr = le32_to_cpu(*(uint32_t *)(d->config +
-                                                         config_ofs));
+
+                    if (pci_bar_is_64bit(r)) {
+                        new_addr = le64_to_cpu(*(uint64_t *)(d->config +
+                                                             config_ofs));
+                    } else {
+                        new_addr = le32_to_cpu(*(uint32_t *)(d->config +
+                                                             config_ofs));
+                    }
                     /* the ROM slot has a specific enable bit */
                     if (i == PCI_ROM_SLOT && !(new_addr & 1))
                         goto no_mem_map;
@@ -479,7 +491,7 @@ static void pci_update_mappings(PCIDevice *d)
 
                         /* keep old behaviour
                          * without this, PC ide doesn't work well. */
-                        last_addr >= UINT32_MAX) {
+                        (!pci_bar_is_64bit(r) && last_addr >= UINT32_MAX)) {
                         new_addr = PCI_BAR_UNMAPPED;
                     }
                 } else {
@@ -738,7 +750,29 @@ static void pci_info_device(PCIDevice *d)
                 monitor_printf(mon, "I/O at 0x%04"PRIx64" [0x%04"PRIx64"].\n",
                                r->addr, r->addr + r->size - 1);
             } else {
-                monitor_printf(mon, "32 bit memory at 0x%08"PRIx64" [0x%08"PRIx64"].\n",
+                const char *type;
+                const char* prefetch;
+
+                switch (r->type & PCI_ADDRESS_SPACE_MEM_TYPE_MASK) {
+                case PCI_ADDRESS_SPACE_MEM:
+                    type = "32 bit";
+                    break;
+                case PCI_ADDRESS_SPACE_MEM_64:
+                    type = "64 bit";
+                    break;
+                default:
+                    type = "unknown";
+                    break;
+                }
+
+                prefetch = "";
+                if (r->type & PCI_ADDRESS_SPACE_MEM_PREFETCH) {
+                    prefetch = " prefetchable";
+                }
+
+                monitor_printf(mon, "%s%s memory at "
+                               "0x%08"PRIx64" [0x%08"PRIx64"].\n",
+                               type, prefetch,
                                r->addr, r->addr + r->size - 1);
             }
         }
diff --git a/hw/pci.h b/hw/pci.h
index 72a78af..b814342 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -81,6 +81,8 @@ typedef int PCIUnregisterFunc(PCIDevice *pci_dev);
 
 #define PCI_ADDRESS_SPACE_MEM		0x00
 #define PCI_ADDRESS_SPACE_IO		0x01
+#define PCI_ADDRESS_SPACE_MEM_64        0x04    /* 64 bit address */
+#define PCI_ADDRESS_SPACE_MEM_TYPE_MASK 0x06
 #define PCI_ADDRESS_SPACE_MEM_PREFETCH	0x08
 
 typedef struct PCIIORegion {
@@ -91,6 +93,13 @@ typedef struct PCIIORegion {
     PCIMapIORegionFunc *map_func;
 } PCIIORegion;
 
+static inline int pci_bar_is_64bit(const PCIIORegion *r)
+{
+    return !(r->type & PCI_ADDRESS_SPACE_IO) &&
+        ((r->type & PCI_ADDRESS_SPACE_MEM_TYPE_MASK) ==
+         PCI_ADDRESS_SPACE_MEM_64);
+}
+
 #define PCI_ROM_SLOT 6
 #define PCI_NUM_REGIONS 7
 
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 27/61] pci: clean up of pci_update_mappings()
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (25 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 26/61] pci: 64bit bar support Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 28/61] pci: factor out while(bus) bus->next loop logic into pci_find_bus_from() Isaku Yamahata
                   ` (37 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

This patch cleans up pci_update_mappings() making it more readable.
- reduce indent level by one or two
- remove duplicated logic.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |  142 ++++++++++++++++++++++++++++++++-----------------------------
 1 files changed, 74 insertions(+), 68 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index beda5ef..6a28fa5 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -440,91 +440,97 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
 static void pci_update_mappings(PCIDevice *d)
 {
     PCIIORegion *r;
-    int cmd, i;
+    int i;
+    uint16_t cmd;
+    uint64_t bar;
+    uint64_t max_addr;
     uint64_t last_addr, new_addr;
     uint32_t config_ofs;
 
     cmd = le16_to_cpu(*(uint16_t *)(d->config + PCI_COMMAND));
     for(i = 0; i < PCI_NUM_REGIONS; i++) {
         r = &d->io_regions[i];
+        if (r->size == 0)
+            continue;
+
         if (i == PCI_ROM_SLOT) {
             config_ofs = 0x30;
         } else {
             config_ofs = 0x10 + i * 4;
         }
-        if (r->size != 0) {
+
+        if (pci_bar_is_64bit(r)) {
+            bar = le64_to_cpu(*(uint64_t *)(d->config + config_ofs));
+        } else {
+            bar = le32_to_cpu(*(uint32_t *)(d->config + config_ofs));
+        }
+
+        new_addr = PCI_BAR_UNMAPPED;
+        last_addr = 0;
+        max_addr = 0;
+        if (r->type & PCI_ADDRESS_SPACE_IO) {
+            if (cmd & PCI_COMMAND_IO) {
+                new_addr = bar;
+            }
+
+            /* NOTE: we have only 64K ioports on PC */
+            max_addr = 0x10000;
+        } else {
+            if (cmd & PCI_COMMAND_MEMORY) {
+                new_addr = bar;
+            }
+
+            /* the ROM slot has a specific enable bit */
+            if (i == PCI_ROM_SLOT && !(bar & 1)) {
+                new_addr = PCI_BAR_UNMAPPED;
+            }
+
+            max_addr = PCI_BAR_UNMAPPED;
+            if (!pci_bar_is_64bit(r)) {
+                /* keep old behaviour
+                   without this, PC ide doesn't work well. */
+                max_addr = UINT32_MAX;
+            }
+        }
+
+        new_addr = new_addr & ~(r->size - 1);
+        last_addr = new_addr + r->size - 1;
+
+        /* NOTE: we do not support wrapping */
+        /* XXX: as we cannot support really dynamic
+           mappings, we handle specific values as invalid
+           mappings. */
+        if (last_addr <= new_addr || new_addr == 0 || last_addr >= max_addr) {
+            new_addr = PCI_BAR_UNMAPPED;
+        }
+
+        if (new_addr == r->addr) {
+            continue;
+        }
+
+        /* now do the real mapping */
+        if (r->addr != PCI_BAR_UNMAPPED) {
             if (r->type & PCI_ADDRESS_SPACE_IO) {
-                if (cmd & PCI_COMMAND_IO) {
-                    new_addr = le32_to_cpu(*(uint32_t *)(d->config +
-                                                         config_ofs));
-                    new_addr = new_addr & ~(r->size - 1);
-                    last_addr = new_addr + r->size - 1;
-                    /* NOTE: we have only 64K ioports on PC */
-                    if (last_addr <= new_addr || new_addr == 0 ||
-                        last_addr >= 0x10000) {
-                        new_addr = PCI_BAR_UNMAPPED;
-                    }
+                int class;
+                /* NOTE: specific hack for IDE in PC case:
+                   only one byte must be mapped. */
+                class = d->config[0x0a] | (d->config[0x0b] << 8);
+                if (class == 0x0101 && r->size == 4) {
+                    isa_unassign_ioport(r->addr + 2, 1);
                 } else {
-                    new_addr = PCI_BAR_UNMAPPED;
+                    isa_unassign_ioport(r->addr, r->size);
                 }
             } else {
-                if (cmd & PCI_COMMAND_MEMORY) {
-
-                    if (pci_bar_is_64bit(r)) {
-                        new_addr = le64_to_cpu(*(uint64_t *)(d->config +
-                                                             config_ofs));
-                    } else {
-                        new_addr = le32_to_cpu(*(uint32_t *)(d->config +
-                                                             config_ofs));
-                    }
-                    /* the ROM slot has a specific enable bit */
-                    if (i == PCI_ROM_SLOT && !(new_addr & 1))
-                        goto no_mem_map;
-                    new_addr = new_addr & ~(r->size - 1);
-                    last_addr = new_addr + r->size - 1;
-                    /* NOTE: we do not support wrapping */
-                    /* XXX: as we cannot support really dynamic
-                       mappings, we handle specific values as invalid
-                       mappings. */
-                    if (last_addr <= new_addr || new_addr == 0 ||
-                        last_addr == PCI_BAR_UNMAPPED ||
-
-                        /* keep old behaviour
-                         * without this, PC ide doesn't work well. */
-                        (!pci_bar_is_64bit(r) && last_addr >= UINT32_MAX)) {
-                        new_addr = PCI_BAR_UNMAPPED;
-                    }
-                } else {
-                no_mem_map:
-                    new_addr = PCI_BAR_UNMAPPED;
-                }
-            }
-            /* now do the real mapping */
-            if (new_addr != r->addr) {
-                if (r->addr != PCI_BAR_UNMAPPED) {
-                    if (r->type & PCI_ADDRESS_SPACE_IO) {
-                        int class;
-                        /* NOTE: specific hack for IDE in PC case:
-                           only one byte must be mapped. */
-                        class = d->config[0x0a] | (d->config[0x0b] << 8);
-                        if (class == 0x0101 && r->size == 4) {
-                            isa_unassign_ioport(r->addr + 2, 1);
-                        } else {
-                            isa_unassign_ioport(r->addr, r->size);
-                        }
-                    } else {
-                        cpu_register_physical_memory(pci_to_cpu_addr(r->addr),
-                                                     r->size,
-                                                     IO_MEM_UNASSIGNED);
-                        qemu_unregister_coalesced_mmio(r->addr, r->size);
-                    }
-                }
-                r->addr = new_addr;
-                if (r->addr != PCI_BAR_UNMAPPED) {
-                    r->map_func(d, i, r->addr, r->size, r->type);
-                }
+                cpu_register_physical_memory(pci_to_cpu_addr(r->addr),
+                                             r->size,
+                                             IO_MEM_UNASSIGNED);
+                qemu_unregister_coalesced_mmio(r->addr, r->size);
             }
         }
+        r->addr = new_addr;
+        if (r->addr != PCI_BAR_UNMAPPED) {
+            r->map_func(d, i, r->addr, r->size, r->type);
+        }
     }
 }
 
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 28/61] pci: factor out while(bus) bus->next loop logic into pci_find_bus_from().
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (26 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 27/61] pci: clean up of pci_update_mappings() Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 29/61] pci: factor out the logic to get pci device from address Isaku Yamahata
                   ` (36 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

factor out while(bus) bus->next loop logic into pci_find_bus_from()
which will be used later.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |   26 ++++++++++++++------------
 1 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 6a28fa5..5d6b3ea 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -577,6 +577,16 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
         pci_update_mappings(d);
 }
 
+static PCIBus *pci_find_bus_from(PCIBus *from, int bus_num)
+{
+    PCIBus *s = from;
+
+    while (s && s->bus_num != bus_num)
+        s = s->next;
+
+    return s;
+}
+
 void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
 {
     PCIBus *s = opaque;
@@ -588,8 +598,7 @@ void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
                 addr, val, len);
 #endif
     bus_num = (addr >> 16) & 0xff;
-    while (s && s->bus_num != bus_num)
-        s = s->next;
+    s = pci_find_bus_from(s, bus_num);
     if (!s)
         return;
     pci_dev = s->devices[(addr >> 8) & 0xff];
@@ -610,8 +619,7 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
     uint32_t val;
 
     bus_num = (addr >> 16) & 0xff;
-    while (s && s->bus_num != bus_num)
-        s= s->next;
+    s = pci_find_bus_from(s, bus_num);
     if (!s)
         goto fail;
     pci_dev = s->devices[(addr >> 8) & 0xff];
@@ -795,8 +803,7 @@ void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d))
     PCIDevice *d;
     int devfn;
 
-    while (bus && bus->bus_num != bus_num)
-        bus = bus->next;
+    bus = pci_find_bus_from(bus, bus_num);
     if (bus) {
         for(devfn = 0; devfn < 256; devfn++) {
             d = bus->devices[devfn];
@@ -896,12 +903,7 @@ static void pci_bridge_write_config(PCIDevice *d,
 
 PCIBus *pci_find_bus(int bus_num)
 {
-    PCIBus *bus = first_bus;
-
-    while (bus && bus->bus_num != bus_num)
-        bus = bus->next;
-
-    return bus;
+    return pci_find_bus_from(first_bus, bus_num);
 }
 
 PCIDevice *pci_find_device(int bus_num, int slot, int function)
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 29/61] pci: factor out the logic to get pci device from address.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (27 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 28/61] pci: factor out while(bus) bus->next loop logic into pci_find_bus_from() Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 30/61] pci_host.h: split non-inline static function in pci_host.h into pci_host_c.h Isaku Yamahata
                   ` (35 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

factor out conversion logic from io port address into bus+dev+func
with bit shift operation and conversion bus+dev+func into pci device.
They will be used later.
This patch also eliminates the logic duplication.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |  105 ++++++++++++++++++++++++++++++++++---------------------------
 1 files changed, 58 insertions(+), 47 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 5d6b3ea..d1745ab 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -587,71 +587,82 @@ static PCIBus *pci_find_bus_from(PCIBus *from, int bus_num)
     return s;
 }
 
-void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
+static PCIDevice *pci_bdf_to_dev(PCIBus *s, int bus_num, unsigned int devfn)
 {
-    PCIBus *s = opaque;
-    PCIDevice *pci_dev;
-    int config_addr, bus_num;
-
-#if 0
-    PCI_DPRINTF("pci_data_write: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
-                addr, val, len);
-#endif
-    bus_num = (addr >> 16) & 0xff;
     s = pci_find_bus_from(s, bus_num);
     if (!s)
-        return;
-    pci_dev = s->devices[(addr >> 8) & 0xff];
+        return NULL;
+
+    return s->devices[devfn];
+}
+
+static void pci_dev_data_write(PCIDevice *pci_dev,
+                               uint32_t config_addr, uint32_t val, int len)
+{
+    assert(len == 1 || len == 2 || len == 4);
     if (!pci_dev)
         return;
-    config_addr = addr & 0xff;
-    PCI_DPRINTF("pci_config_write: %s: "
-                "addr=%02"PRIx32" val=%08"PRI32x" len=%d\n",
-                pci_dev->name, config_addr, val, len);
+
+    PCI_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRI32x" len=%d\n",
+                __func__, pci_dev->name, config_addr, val, len);
     pci_dev->config_write(pci_dev, config_addr, val, len);
 }
 
-uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
+static uint32_t pci_dev_data_read(PCIDevice *pci_dev,
+                                  uint32_t config_addr, int len)
 {
-    PCIBus *s = opaque;
-    PCIDevice *pci_dev;
-    int config_addr, bus_num;
     uint32_t val;
 
-    bus_num = (addr >> 16) & 0xff;
-    s = pci_find_bus_from(s, bus_num);
-    if (!s)
-        goto fail;
-    pci_dev = s->devices[(addr >> 8) & 0xff];
+    assert(len == 1 || len == 2 || len == 4);
     if (!pci_dev) {
-    fail:
-        switch(len) {
-        case 1:
-            val = 0xff;
-            break;
-        case 2:
-            val = 0xffff;
-            break;
-        default:
-        case 4:
-            val = 0xffffffff;
-            break;
-        }
-        goto the_end;
+        val = (1 << (len * 8)) - 1;
+    } else {
+        val = pci_dev->config_read(pci_dev, config_addr, len);
+        PCI_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRIx32" len=%d\n",
+                    __func__, pci_dev->name, config_addr, val, len);
     }
-    config_addr = addr & 0xff;
-    val = pci_dev->config_read(pci_dev, config_addr, len);
-    PCI_DPRINTF("pci_config_read: %s: "
-                "addr=%02"PRIx32" val=%08"PRIx32" len=%d\n",
-                pci_dev->name, config_addr, val, len);
- the_end:
+
 #if 0
-    PCI_DPRINTF("pci_data_read: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
-                addr, val, len);
+    PCI_DPRINTF("%s: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
+                __func__, addr, val, len);
 #endif
     return val;
 }
 
+static void pci_addr_to_dev(PCIBus *s, uint32_t addr,
+                            PCIDevice **pci_dev, uint32_t *config_addr)
+{
+    int bus_num = (addr >> 16) & 0xff;
+    unsigned int devfn = (addr >> 8) & 0xff;
+
+    *pci_dev = pci_bdf_to_dev(s, bus_num, devfn);
+    *config_addr = addr & 0xff;
+}
+
+void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
+{
+    PCIBus *s = opaque;
+    PCIDevice *pci_dev;
+    uint32_t config_addr;
+
+#if 0
+    PCI_DPRINTF("pci_data_write: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
+                addr, val, len);
+#endif
+
+    pci_addr_to_dev(s, addr, &pci_dev, &config_addr);
+    pci_dev_data_write(pci_dev, config_addr, val, len);
+}
+
+uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
+{
+    PCIBus *s = opaque;
+    PCIDevice *pci_dev;
+    uint32_t config_addr;
+
+    pci_addr_to_dev(s, addr, &pci_dev, &config_addr);
+    return pci_dev_data_read(pci_dev, config_addr, len);
+}
 /***********************************************************/
 /* generic PCI irq support */
 
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 30/61] pci_host.h: split non-inline static function in pci_host.h into pci_host_c.h
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (28 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 29/61] pci: factor out the logic to get pci device from address Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 31/61] pci: pcie host and mmcfg support Isaku Yamahata
                   ` (34 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

Later a structures declared in pci_host.h, PCIHostState, will be used.
However pci_host.h doesn't allow to include itself easily. This patches
addresses it.

pci_host.h includes non-inline static functions which are instantiated
in .c by including pci_host.h. That prevents from including pci_host.h
to use PCIHostState.
So split pci_host.h non-inline static functions into pci_host_c.h.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/apb_pci.c                    |    2 +-
 hw/grackle_pci.c                |    2 +-
 hw/gt64xxx.c                    |    2 +-
 hw/pci_host.h                   |   88 +-------------------------------------
 hw/{pci_host.h => pci_host_c.h} |    8 +---
 hw/piix_pci.c                   |    2 +-
 hw/ppc4xx_pci.c                 |    2 +-
 hw/ppce500_pci.c                |    2 +-
 hw/prep_pci.c                   |    2 +-
 hw/unin_pci.c                   |    2 +-
 10 files changed, 12 insertions(+), 100 deletions(-)
 copy hw/{pci_host.h => pci_host_c.h} (96%)

diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index eb77042..c2fe5bf 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -40,7 +40,7 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
 #endif
 
 typedef target_phys_addr_t pci_addr_t;
-#include "pci_host.h"
+#include "pci_host_c.h"
 
 typedef struct APBState {
     SysBusDevice busdev;
diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
index d878cf6..59664b7 100644
--- a/hw/grackle_pci.c
+++ b/hw/grackle_pci.c
@@ -38,7 +38,7 @@
 #endif
 
 typedef target_phys_addr_t pci_addr_t;
-#include "pci_host.h"
+#include "pci_host_c.h"
 
 typedef struct GrackleState {
     SysBusDevice busdev;
diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c
index 8f9ae4a..f8d0dcc 100644
--- a/hw/gt64xxx.c
+++ b/hw/gt64xxx.c
@@ -28,7 +28,7 @@
 #include "pc.h"
 
 typedef target_phys_addr_t pci_addr_t;
-#include "pci_host.h"
+#include "pci_host_c.h"
 
 //#define DEBUG
 
diff --git a/hw/pci_host.h b/hw/pci_host.h
index 48862b5..9f272a7 100644
--- a/hw/pci_host.h
+++ b/hw/pci_host.h
@@ -25,97 +25,15 @@
 /* Worker routines for a PCI host controller that uses an {address,data}
    register pair to access PCI configuration space.  */
 
-/* debug PCI */
-//#define DEBUG_PCI
+#ifndef PCI_HOST_H
+#define PCI_HOST_H
 
 #include "sysbus.h"
 
-#ifdef DEBUG_PCI
-#define PCI_DPRINTF(fmt, ...) \
-do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define PCI_DPRINTF(fmt, ...)
-#endif
-
 typedef struct {
     SysBusDevice busdev;
     uint32_t config_reg;
     PCIBus *bus;
 } PCIHostState;
 
-static void pci_host_data_writeb(void* opaque, pci_addr_t addr, uint32_t val)
-{
-    PCIHostState *s = opaque;
-
-    PCI_DPRINTF("writeb addr " TARGET_FMT_plx " val %x\n",
-                (target_phys_addr_t)addr, val);
-    if (s->config_reg & (1u << 31))
-        pci_data_write(s->bus, s->config_reg | (addr & 3), val, 1);
-}
-
-static void pci_host_data_writew(void* opaque, pci_addr_t addr, uint32_t val)
-{
-    PCIHostState *s = opaque;
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap16(val);
-#endif
-    PCI_DPRINTF("writew addr " TARGET_FMT_plx " val %x\n",
-                (target_phys_addr_t)addr, val);
-    if (s->config_reg & (1u << 31))
-        pci_data_write(s->bus, s->config_reg | (addr & 3), val, 2);
-}
-
-static void pci_host_data_writel(void* opaque, pci_addr_t addr, uint32_t val)
-{
-    PCIHostState *s = opaque;
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
-    PCI_DPRINTF("writel addr " TARGET_FMT_plx " val %x\n",
-                (target_phys_addr_t)addr, val);
-    if (s->config_reg & (1u << 31))
-        pci_data_write(s->bus, s->config_reg, val, 4);
-}
-
-static uint32_t pci_host_data_readb(void* opaque, pci_addr_t addr)
-{
-    PCIHostState *s = opaque;
-    uint32_t val;
-
-    if (!(s->config_reg & (1 << 31)))
-        return 0xff;
-    val = pci_data_read(s->bus, s->config_reg | (addr & 3), 1);
-    PCI_DPRINTF("readb addr " TARGET_FMT_plx " val %x\n",
-                (target_phys_addr_t)addr, val);
-    return val;
-}
-
-static uint32_t pci_host_data_readw(void* opaque, pci_addr_t addr)
-{
-    PCIHostState *s = opaque;
-    uint32_t val;
-    if (!(s->config_reg & (1 << 31)))
-        return 0xffff;
-    val = pci_data_read(s->bus, s->config_reg | (addr & 3), 2);
-    PCI_DPRINTF("readw addr " TARGET_FMT_plx " val %x\n",
-                (target_phys_addr_t)addr, val);
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap16(val);
-#endif
-    return val;
-}
-
-static uint32_t pci_host_data_readl(void* opaque, pci_addr_t addr)
-{
-    PCIHostState *s = opaque;
-    uint32_t val;
-    if (!(s->config_reg & (1 << 31)))
-        return 0xffffffff;
-    val = pci_data_read(s->bus, s->config_reg | (addr & 3), 4);
-    PCI_DPRINTF("readl addr " TARGET_FMT_plx " val %x\n",
-                (target_phys_addr_t)addr, val);
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
-    return val;
-}
+#endif /* PCI_HOST_H */
diff --git a/hw/pci_host.h b/hw/pci_host_c.h
similarity index 96%
copy from hw/pci_host.h
copy to hw/pci_host_c.h
index 48862b5..fcd7e6e 100644
--- a/hw/pci_host.h
+++ b/hw/pci_host_c.h
@@ -28,7 +28,7 @@
 /* debug PCI */
 //#define DEBUG_PCI
 
-#include "sysbus.h"
+#include "pci_host.h"
 
 #ifdef DEBUG_PCI
 #define PCI_DPRINTF(fmt, ...) \
@@ -37,12 +37,6 @@ do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
 #define PCI_DPRINTF(fmt, ...)
 #endif
 
-typedef struct {
-    SysBusDevice busdev;
-    uint32_t config_reg;
-    PCIBus *bus;
-} PCIHostState;
-
 static void pci_host_data_writeb(void* opaque, pci_addr_t addr, uint32_t val)
 {
     PCIHostState *s = opaque;
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index 7447663..329aa45 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -29,7 +29,7 @@
 #include "sysbus.h"
 
 typedef uint32_t pci_addr_t;
-#include "pci_host.h"
+#include "pci_host_c.h"
 
 typedef PCIHostState I440FXState;
 
diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
index 655fe86..01b8eb1 100644
--- a/hw/ppc4xx_pci.c
+++ b/hw/ppc4xx_pci.c
@@ -25,7 +25,7 @@
 
 typedef target_phys_addr_t pci_addr_t;
 #include "pci.h"
-#include "pci_host.h"
+#include "pci_host_c.h"
 #include "bswap.h"
 
 #undef DEBUG
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index 64fccfd..e388a9a 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -19,7 +19,7 @@
 #include "ppce500.h"
 typedef target_phys_addr_t pci_addr_t;
 #include "pci.h"
-#include "pci_host.h"
+#include "pci_host_c.h"
 #include "bswap.h"
 #include "qemu-log.h"
 
diff --git a/hw/prep_pci.c b/hw/prep_pci.c
index 2d8a0fa..72498bf 100644
--- a/hw/prep_pci.c
+++ b/hw/prep_pci.c
@@ -26,7 +26,7 @@
 #include "pci.h"
 
 typedef uint32_t pci_addr_t;
-#include "pci_host.h"
+#include "pci_host_c.h"
 
 typedef PCIHostState PREPPCIState;
 
diff --git a/hw/unin_pci.c b/hw/unin_pci.c
index a202153..ac69b7f 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -36,7 +36,7 @@
 #endif
 
 typedef target_phys_addr_t pci_addr_t;
-#include "pci_host.h"
+#include "pci_host_c.h"
 
 typedef struct UNINState {
     SysBusDevice busdev;
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 31/61] pci: pcie host and mmcfg support.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (29 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 30/61] pci_host.h: split non-inline static function in pci_host.h into pci_host_c.h Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 32/61] pci: helper functions to access PCIDevice::config Isaku Yamahata
                   ` (33 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

This patch adds common routines for pcie host bridge and pcie mmcfg.
This will be used by q35 based chipset emulation.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/hw.h       |   12 +++
 hw/pci.c      |  266 +++++++++++++++++++++++++++++++++++++++++++++++++++------
 hw/pci.h      |   36 +++++++-
 hw/pci_host.h |   22 +++++
 4 files changed, 304 insertions(+), 32 deletions(-)

diff --git a/hw/hw.h b/hw/hw.h
index cf266b3..478b0b2 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -428,6 +428,18 @@ extern const VMStateDescription vmstate_pci_device;
             + type_check(PCIDevice,typeof_field(_state, _field))     \
 }
 
+extern const VMStateDescription vmstate_pcie_device;
+
+#define VMSTATE_PCIE_DEVICE(_field, _state) {                        \
+    .name       = (stringify(_field)),                               \
+    .version_id = 2,                                                 \
+    .size       = sizeof(PCIDevice),                                 \
+    .vmsd       = &vmstate_pcie_device,                              \
+    .flags      = VMS_STRUCT,                                        \
+    .offset     = offsetof(_state, _field)                           \
+            + type_check(PCIDevice,typeof_field(_state, _field))     \
+}
+
 /* _f : field name
    _f_n : num of elements field_name
    _n : num of elements
diff --git a/hw/pci.c b/hw/pci.c
index d1745ab..29bca12 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -23,6 +23,7 @@
  */
 #include "hw.h"
 #include "pci.h"
+#include "pci_host.h"
 #include "monitor.h"
 #include "net.h"
 #include "sysemu.h"
@@ -141,9 +142,12 @@ int pci_bus_num(PCIBus *s)
 static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
 {
     PCIDevice *s = container_of(pv, PCIDevice, config);
-    uint8_t config[size];
+    uint8_t *config;
     int i;
 
+    assert(size == pcie_config_size(s));
+    config = qemu_malloc(size * sizeof(config[0]));
+
     qemu_get_buffer(f, config, size);
     for (i = 0; i < size; ++i)
         if ((config[i] ^ s->config[i]) & s->cmask[i] & ~s->wmask[i])
@@ -152,6 +156,7 @@ static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
 
     pci_update_mappings(s);
 
+    qemu_free(config);
     return 0;
 }
 
@@ -159,6 +164,7 @@ static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
 static void put_pci_config_device(QEMUFile *f, const void *pv, size_t size)
 {
     const uint8_t *v = pv;
+    assert(size == pcie_config_size(container_of(pv, PCIDevice, config)));
     qemu_put_buffer(f, v, size);
 }
 
@@ -168,6 +174,17 @@ static VMStateInfo vmstate_info_pci_config = {
     .put  = put_pci_config_device,
 };
 
+#define VMSTATE_PCI_CONFIG(_field, _state, _version, _info, _type,   \
+                           _size) {                                  \
+    .name       = (stringify(_field)),                               \
+    .version_id = (_version),                                        \
+    .size       = (_size),                                           \
+    .info       = &(_info),                                          \
+    .flags      = VMS_SINGLE | VMS_POINTER,                          \
+    .offset     = offsetof(_state, _field)                           \
+            + type_check(_type,typeof_field(_state, _field))         \
+}
+
 const VMStateDescription vmstate_pci_device = {
     .name = "PCIDevice",
     .version_id = 2,
@@ -175,21 +192,46 @@ const VMStateDescription vmstate_pci_device = {
     .minimum_version_id_old = 1,
     .fields      = (VMStateField []) {
         VMSTATE_INT32_LE(version_id, PCIDevice),
-        VMSTATE_SINGLE(config, PCIDevice, 0, vmstate_info_pci_config,
-                       typeof_field(PCIDevice,config)),
+        VMSTATE_PCI_CONFIG(config, PCIDevice, 0, vmstate_info_pci_config,
+                           typeof_field(PCIDevice, config),
+                           PCI_CONFIG_SPACE_SIZE),
         VMSTATE_INT32_ARRAY_V(irq_state, PCIDevice, PCI_NUM_PINS, 2),
         VMSTATE_END_OF_LIST()
     }
 };
 
+const VMStateDescription vmstate_pcie_device = {
+    .name = "PCIDevice",
+    .version_id = 2,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField []) {
+        VMSTATE_INT32_LE(version_id, PCIDevice),
+        VMSTATE_PCI_CONFIG(config, PCIDevice, 0, vmstate_info_pci_config,
+                           typeof_field(PCIDevice, config),
+                           PCIE_CONFIG_SPACE_SIZE),
+        VMSTATE_INT32_ARRAY_V(irq_state, PCIDevice, PCI_NUM_PINS, 2),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription *pci_get_vmstate(PCIDevice *s)
+{
+    if (pci_is_pcie(s)) {
+        return &vmstate_pcie_device;
+    }
+
+    return &vmstate_pci_device;
+}
+
 void pci_device_save(PCIDevice *s, QEMUFile *f)
 {
-    vmstate_save_state(f, &vmstate_pci_device, s);
+    vmstate_save_state(f, pci_get_vmstate(s), s);
 }
 
 int pci_device_load(PCIDevice *s, QEMUFile *f)
 {
-    return vmstate_load_state(f, &vmstate_pci_device, s, s->version_id);
+    return vmstate_load_state(f, pci_get_vmstate(s), s, s->version_id);
 }
 
 static int pci_set_default_subsystem_id(PCIDevice *pci_dev)
@@ -298,14 +340,31 @@ static void pci_init_cmask(PCIDevice *dev)
 static void pci_init_wmask(PCIDevice *dev)
 {
     int i;
+    uint32_t config_size = pcie_config_size(dev);
+
     dev->wmask[PCI_CACHE_LINE_SIZE] = 0xff;
     dev->wmask[PCI_INTERRUPT_LINE] = 0xff;
     dev->wmask[PCI_COMMAND] = PCI_COMMAND_IO | PCI_COMMAND_MEMORY
                               | PCI_COMMAND_MASTER;
-    for (i = PCI_CONFIG_HEADER_SIZE; i < PCI_CONFIG_SPACE_SIZE; ++i)
+    for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; ++i)
         dev->wmask[i] = 0xff;
 }
 
+static void pci_config_init(PCIDevice *pci_dev)
+{
+    int config_size = pcie_config_size(pci_dev);
+#define PCI_CONFIG_ALLOC(d, member, size)                               \
+    do {                                                                \
+        (d)->member =                                                   \
+            (typeof((d)->member))qemu_mallocz(sizeof((d)->member[0]) *  \
+                                              size);                    \
+    } while (0)
+    PCI_CONFIG_ALLOC(pci_dev, config, config_size);
+    PCI_CONFIG_ALLOC(pci_dev, cmask, config_size);
+    PCI_CONFIG_ALLOC(pci_dev, wmask, config_size);
+    PCI_CONFIG_ALLOC(pci_dev, used, config_size);
+}
+
 /* -1 for devfn means auto assign */
 static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
                                          const char *name, int devfn,
@@ -326,6 +385,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
     pci_dev->devfn = devfn;
     pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
     memset(pci_dev->irq_state, 0, sizeof(pci_dev->irq_state));
+    pci_config_init(pci_dev);
     pci_set_default_subsystem_id(pci_dev);
     pci_init_cmask(pci_dev);
     pci_init_wmask(pci_dev);
@@ -534,40 +594,48 @@ static void pci_update_mappings(PCIDevice *d)
     }
 }
 
+static uint8_t pcie_config_get_byte(PCIDevice *d, uint32_t addr)
+{
+    uint8_t *conf = &d->config[addr];
+    if (conf != NULL)
+        return *conf;
+    return 0;
+}
+
+static uint32_t pcie_config_get(PCIDevice *d, uint32_t addr, int len)
+{
+    int i;
+    union {
+        uint8_t val8[4];
+        uint32_t val32;
+    } v = { .val32 = 0 };
+
+    for (i = 0; i < len; i++) {
+        v.val8[i] = pcie_config_get_byte(d, addr + i);
+    }
+
+    return le32_to_cpu(v.val32);
+}
+
 uint32_t pci_default_read_config(PCIDevice *d,
                                  uint32_t address, int len)
 {
-    uint32_t val;
+    uint32_t config_size = pcie_config_size(d);
 
-    switch(len) {
-    default:
-    case 4:
-	if (address <= 0xfc) {
-	    val = le32_to_cpu(*(uint32_t *)(d->config + address));
-	    break;
-	}
-	/* fall through */
-    case 2:
-        if (address <= 0xfe) {
-	    val = le16_to_cpu(*(uint16_t *)(d->config + address));
-	    break;
-	}
-	/* fall through */
-    case 1:
-        val = d->config[address];
-        break;
-    }
-    return val;
+    assert(len == 1 || len == 2 || len == 4);
+    len = MIN(len, config_size - MIN(config_size, address));
+    return pcie_config_get(d, address, len);
 }
 
 void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
 {
     uint8_t orig[PCI_CONFIG_SPACE_SIZE];
     int i;
+    uint32_t config_size = pcie_config_size(d);
 
     /* not efficient, but simple */
     memcpy(orig, d->config, PCI_CONFIG_SPACE_SIZE);
-    for(i = 0; i < l && addr < PCI_CONFIG_SPACE_SIZE; val >>= 8, ++i, ++addr) {
+    for(i = 0; i < l && addr < config_size; val >>= 8, ++i, ++addr) {
         uint8_t wmask = d->wmask[addr];
         d->config[addr] = (d->config[addr] & ~wmask) | (val & wmask);
     }
@@ -663,6 +731,147 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
     pci_addr_to_dev(s, addr, &pci_dev, &config_addr);
     return pci_dev_data_read(pci_dev, config_addr, len);
 }
+
+static void pcie_mmcfg_addr_to_dev(PCIBus *s, uint32_t mmcfg_addr,
+                                   PCIDevice **pci_dev, uint32_t *conf_addr)
+{
+    int bus_num;
+    unsigned int dev;
+    uint8_t func;
+
+#define PCIE_MASK(val, hi_bit, low_bit)                 \
+    (((val) & (((1ULL << (hi_bit)) - 1))) >> (low_bit))
+#define PCIE_VAL(VAL, val)                                              \
+    PCIE_MASK((val), PCIE_MMCFG_ ## VAL ## _HI, PCIE_MMCFG_ ## VAL ## _LOW)
+#define PCIE_MMCFG_BUS_HI               28
+#define PCIE_MMCFG_BUS_LOW              20
+#define PCIE_MMCFG_DEV_HI               19
+#define PCIE_MMCFG_DEV_LOW              15
+#define PCIE_MMCFG_FUNC_HI              14
+#define PCIE_MMCFG_FUNC_LOW             12
+#define PCIE_MMCFG_CONFADDR_HI          11
+#define PCIE_MMCFG_CONFADDR_LOW         0
+#define PCIE_MMCFG_BUS(addr)            PCIE_VAL(BUS, (addr))
+#define PCIE_MMCFG_DEV(addr)            PCIE_VAL(DEV, (addr))
+#define PCIE_MMCFG_FUNC(addr)           PCIE_VAL(FUNC, (addr))
+#define PCIE_MMCFG_CONFADDR(addr)       PCIE_VAL(CONFADDR, (addr))
+
+    bus_num = PCIE_MMCFG_BUS(mmcfg_addr);
+    dev = PCIE_MMCFG_DEV(mmcfg_addr);
+    func = PCIE_MMCFG_FUNC(mmcfg_addr);
+    *conf_addr = PCIE_MMCFG_CONFADDR(mmcfg_addr);
+
+    *pci_dev = pci_bdf_to_dev(s, bus_num, PCI_DEVFN(dev, func));
+}
+
+void pcie_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
+{
+    PCIBus *s = opaque;
+    PCIDevice *pci_dev;
+    uint32_t config_addr;
+
+#if 0
+    PCI_DPRINTF("%s: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
+                __func__, addr, val, len);
+#endif
+    pcie_mmcfg_addr_to_dev(s, addr, &pci_dev, &config_addr);
+    pci_dev_data_write(pci_dev, config_addr, val, len);
+}
+
+uint32_t pcie_data_read(void *opaque, uint32_t addr, int len)
+{
+    PCIBus *s = opaque;
+    PCIDevice *pci_dev;
+    uint32_t config_addr;
+
+    pcie_mmcfg_addr_to_dev(s, addr, &pci_dev, &config_addr);
+    return pci_dev_data_read(pci_dev, config_addr, len);
+}
+
+#define DEFINE_PCIE_HOST_DATA_READ(len)                         \
+    static uint32_t pcie_host_data_read_ ## len (               \
+        void *opaque, target_phys_addr_t addr)                  \
+    {                                                           \
+        PCIExpressHost *e = (PCIExpressHost *)opaque;           \
+        return pcie_data_read(e->pci.bus,                       \
+                              addr - e->base_addr, (len));      \
+    }
+
+#define DEFINE_PCIE_HOST_DATA_WRITE(len)                        \
+    static void pcie_host_data_write_ ## len (                  \
+        void *opaque, target_phys_addr_t addr, uint32_t value)  \
+    {                                                           \
+        PCIExpressHost *e = (PCIExpressHost *)opaque;           \
+        pcie_data_write(e->pci.bus,                             \
+                        addr - e->base_addr, value, (len));     \
+    }
+
+#define DEFINE_PCIE_HOST_DATA_MMIO(len)      \
+        DEFINE_PCIE_HOST_DATA_READ(len)      \
+        DEFINE_PCIE_HOST_DATA_WRITE(len)
+
+DEFINE_PCIE_HOST_DATA_MMIO(1)
+DEFINE_PCIE_HOST_DATA_MMIO(2)
+DEFINE_PCIE_HOST_DATA_MMIO(4)
+
+#define DEFINE_PCIE_MEMORY_FUNCS(Type, type)                            \
+    static CPU ## Type ## MemoryFunc *pcie_host_data_ ## type [] =      \
+    {                                                                   \
+        &pcie_host_data_ ## type ## _1,                                 \
+        &pcie_host_data_ ## type ## _2,                                 \
+        &pcie_host_data_ ## type ## _4,                                 \
+    };
+
+DEFINE_PCIE_MEMORY_FUNCS(Read, read)
+DEFINE_PCIE_MEMORY_FUNCS(Write, write)
+
+int pcie_host_init(PCIExpressHost *e,
+                   CPUReadMemoryFunc **mmcfg_read,
+                   CPUWriteMemoryFunc **mmcfg_write)
+{
+    e->base_addr = PCIE_BASE_ADDR_INVALID;
+
+    if (mmcfg_read == NULL)
+        mmcfg_read = pcie_host_data_read;
+    if (mmcfg_write == NULL)
+        mmcfg_write = pcie_host_data_write;
+    e->mmio_index = cpu_register_io_memory(mmcfg_read, mmcfg_write, e);
+    if (e->mmio_index < 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+void pcie_host_mmcfg_unmap(PCIExpressHost *e)
+{
+    if (e->base_addr != PCIE_BASE_ADDR_INVALID) {
+        cpu_register_physical_memory(e->base_addr, e->size, IO_MEM_UNASSIGNED);
+    }
+}
+
+void pcie_host_mmcfg_map(PCIExpressHost *e,
+                         target_phys_addr_t addr, uint32_t size)
+{
+    assert((size & (size - 1)) == 0); /* power of 2 */
+    assert(size >= (1ULL << PCIE_MMCFG_BUS_LOW));
+    assert(size <= (1ULL << PCIE_MMCFG_BUS_HI));
+
+    e->base_addr = addr;
+    e->size = size;
+    cpu_register_physical_memory(e->base_addr, e->size, e->mmio_index);
+}
+
+void pcie_host_mmcfg_update(PCIExpressHost *e,
+                            int enable,
+                            target_phys_addr_t addr, uint32_t size)
+{
+    pcie_host_mmcfg_unmap(e);
+    if (enable) {
+        pcie_host_mmcfg_map(e, addr, size);
+    }
+}
+
 /***********************************************************/
 /* generic PCI irq support */
 
@@ -1001,9 +1210,10 @@ PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name)
 
 static int pci_find_space(PCIDevice *pdev, uint8_t size)
 {
+    int config_size = pcie_config_size(pdev);
     int offset = PCI_CONFIG_HEADER_SIZE;
     int i;
-    for (i = PCI_CONFIG_HEADER_SIZE; i < PCI_CONFIG_SPACE_SIZE; ++i)
+    for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; ++i)
         if (pdev->used[i])
             offset = i + 1;
         else if (i - offset + 1 == size)
diff --git a/hw/pci.h b/hw/pci.h
index b814342..460a2b5 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -173,20 +173,26 @@ enum {
     QEMU_PCI_CAP_MSIX = 0x1,
 };
 
+/* Size of the standart PCIe config space: 4KB */
+#define PCIE_CONFIG_SPACE_SIZE  0x1000
+#define PCIE_EXT_CONFIG_SPACE_SIZE                      \
+    (PCIE_CONFIG_SPACE_SIZE - PCI_CONFIG_SPACE_SIZE)
+
 struct PCIDevice {
     DeviceState qdev;
+
     /* PCI config space */
-    uint8_t config[PCI_CONFIG_SPACE_SIZE];
+    uint8_t *config;
 
     /* Used to enable config checks on load. Note that writeable bits are
      * never checked even if set in cmask. */
-    uint8_t cmask[PCI_CONFIG_SPACE_SIZE];
+    uint8_t *cmask;
 
     /* Used to implement R/W bytes */
-    uint8_t wmask[PCI_CONFIG_SPACE_SIZE];
+    uint8_t *wmask;
 
     /* Used to allocate config space for capabilities. */
-    uint8_t used[PCI_CONFIG_SPACE_SIZE];
+    uint8_t *used;
 
     /* the following fields are read only */
     PCIBus *bus;
@@ -268,6 +274,8 @@ PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
                         const char *default_devaddr);
 void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len);
 uint32_t pci_data_read(void *opaque, uint32_t addr, int len);
+void pcie_data_write(void *opaque, uint32_t addr, uint32_t val, int len);
+uint32_t pcie_data_read(void *opaque, uint32_t addr, int len);
 int pci_bus_num(PCIBus *s);
 void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d));
 PCIBus *pci_find_bus(int bus_num);
@@ -340,6 +348,9 @@ typedef struct {
     pci_qdev_initfn init;
     PCIConfigReadFunc *config_read;
     PCIConfigWriteFunc *config_write;
+
+    /* pcie stuff */
+    int pcie;
 } PCIDeviceInfo;
 
 void pci_qdev_register(PCIDeviceInfo *info);
@@ -349,6 +360,23 @@ PCIDevice *pci_create(const char *name, const char *devaddr);
 PCIDevice *pci_create_noinit(PCIBus *bus, int devfn, const char *name);
 PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name);
 
+static inline int pci_is_pcie(PCIDevice *d)
+{
+    /*
+     * At the moment, all the pci devices aren't qdevfied. So
+     * d->qdev.info might be NULL.
+     * Given that pcie device emulator hasn't exist, we conclude that
+     * such a device isn't pcie.
+     */
+    return d->qdev.info != NULL &&
+        container_of(d->qdev.info, PCIDeviceInfo, qdev)->pcie;
+}
+
+static inline uint32_t pcie_config_size(PCIDevice *d)
+{
+    return pci_is_pcie(d)? PCIE_CONFIG_SPACE_SIZE: PCI_CONFIG_SPACE_SIZE;
+}
+
 /* lsi53c895a.c */
 #define LSI_MAX_DEVS 7
 
diff --git a/hw/pci_host.h b/hw/pci_host.h
index 9f272a7..6d5ae22 100644
--- a/hw/pci_host.h
+++ b/hw/pci_host.h
@@ -36,4 +36,26 @@ typedef struct {
     PCIBus *bus;
 } PCIHostState;
 
+typedef struct {
+    PCIHostState pci;
+
+    /* express part */
+    target_phys_addr_t  base_addr;
+#define PCIE_BASE_ADDR_INVALID  ((target_phys_addr_t)-1ULL)
+    target_phys_addr_t  size;
+    int bus_num_order;
+    int mmio_index;
+} PCIExpressHost;
+
+int pcie_host_init(PCIExpressHost *e,
+                   CPUReadMemoryFunc **mmcfg_read,
+                   CPUWriteMemoryFunc **mmcfg_write);
+
+void pcie_host_mmcfg_unmap(PCIExpressHost *e);
+void pcie_host_mmcfg_map(PCIExpressHost *e,
+                         target_phys_addr_t addr, uint32_t size);
+void pcie_host_mmcfg_update(PCIExpressHost *e,
+                            int enable,
+                            target_phys_addr_t addr, uint32_t size);
+
 #endif /* PCI_HOST_H */
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 32/61] pci: helper functions to access PCIDevice::config
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (30 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 31/61] pci: pcie host and mmcfg support Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 10:47   ` [Qemu-devel] " Michael S. Tsirkin
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 33/61] pci: use the symbolic constant, PCI_ROM_ADDRESS_ENABLE instead of 1 Isaku Yamahata
                   ` (32 subsequent siblings)
  64 siblings, 1 reply; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

add helper functions to get/set PCIDevice::config
Those will be used later.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.h |   60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 60 insertions(+), 0 deletions(-)

diff --git a/hw/pci.h b/hw/pci.h
index 460a2b5..e3f5df8 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -325,6 +325,18 @@ pci_get_long(uint8_t *config)
 }
 
 static inline void
+pci_set_quad(uint8_t *config, uint64_t val)
+{
+    cpu_to_le64w((uint64_t *)config, val);
+}
+
+static inline uint64_t
+pci_get_quad(uint8_t *config)
+{
+    return le64_to_cpup((uint64_t *)config);
+}
+
+static inline void
 pci_config_set_vendor_id(uint8_t *pci_config, uint16_t val)
 {
     pci_set_word(&pci_config[PCI_VENDOR_ID], val);
@@ -342,6 +354,54 @@ pci_config_set_class(uint8_t *pci_config, uint16_t val)
     pci_set_word(&pci_config[PCI_CLASS_DEVICE], val);
 }
 
+static inline void
+pci_config_set_byte(PCIDevice *d, uint32_t addr, uint8_t val)
+{
+    pci_set_byte(&d->config[addr], val);
+}
+
+static inline void
+pci_config_set_word(PCIDevice *d, uint32_t addr, uint16_t val)
+{
+    pci_set_word(&d->config[addr], val);
+}
+
+static inline void
+pci_config_set_long(PCIDevice *d, uint32_t addr, uint32_t val)
+{
+    pci_set_long(&d->config[addr], val);
+}
+
+static inline void
+pci_config_set_quad(PCIDevice *d, uint32_t addr, uint64_t val)
+{
+    pci_set_quad(&d->config[addr], val);
+}
+
+static inline uint8_t
+pci_config_get_byte(PCIDevice *d, uint32_t addr)
+{
+    return pci_get_byte(&d->config[addr]);
+}
+
+static inline uint16_t
+pci_config_get_word(PCIDevice *d, uint32_t addr)
+{
+    return pci_get_word(&d->config[addr]);
+}
+
+static inline uint32_t
+pci_config_get_long(PCIDevice *d, uint32_t addr)
+{
+    return pci_get_long(&d->config[addr]);
+}
+
+static inline uint64_t
+pci_config_get_quad(PCIDevice *d, uint32_t addr)
+{
+    return pci_get_quad(&d->config[addr]);
+}
+
 typedef int (*pci_qdev_initfn)(PCIDevice *dev);
 typedef struct {
     DeviceInfo qdev;
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 33/61] pci: use the symbolic constant, PCI_ROM_ADDRESS_ENABLE instead of 1.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (31 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 32/61] pci: helper functions to access PCIDevice::config Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 34/61] pci: introduce pci_swizzle_map_irq_fn() for interrupt pin swizzle Isaku Yamahata
                   ` (31 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

use the symbolic constant, PCI_ROM_ADDRESS_ENABLE instead of 1.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |    2 +-
 hw/pci.h |    2 ++
 2 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 29bca12..954fc57 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -482,7 +482,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
     if (region_num == PCI_ROM_SLOT) {
         addr = 0x30;
         /* ROM enable bit is writeable */
-        wmask |= 1;
+        wmask |= PCI_ROM_ADDRESS_ENABLE;
     } else {
         addr = 0x10 + region_num * 4;
     }
diff --git a/hw/pci.h b/hw/pci.h
index e3f5df8..ce72020 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -141,6 +141,8 @@ static inline int pci_bar_is_64bit(const PCIIORegion *r)
 #define PCI_SUBVENDOR_ID        0x2c    /* obsolete, use PCI_SUBSYSTEM_VENDOR_ID */
 #define PCI_SUBDEVICE_ID        0x2e    /* obsolete, use PCI_SUBSYSTEM_ID */
 
+#define  PCI_ROM_ADDRESS_ENABLE 0x01
+
 /* Bits in the PCI Status Register (PCI 2.3 spec) */
 #define PCI_STATUS_RESERVED1	0x007
 #define PCI_STATUS_INT_STATUS	0x008
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 34/61] pci: introduce pci_swizzle_map_irq_fn() for interrupt pin swizzle.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (32 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 33/61] pci: use the symbolic constant, PCI_ROM_ADDRESS_ENABLE instead of 1 Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 35/61] piix_pci: use pci_swizzle_map_irq_fn() Isaku Yamahata
                   ` (30 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

introduce pci_swizzle_map_irq_fn() for interrupt pin swizzle.
PCI bridge swizzle is common logic, by introducing this function
duplicated swizzle logic will be avoided later.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |    6 ++++++
 hw/pci.h |    2 ++
 2 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 954fc57..b358d80 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -898,6 +898,12 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
     bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
 }
 
+/* 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD */
+int pci_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin)
+{
+    return (pin + PCI_SLOT(pci_dev->devfn) - 1) % PCI_NUM_PINS;
+}
+
 /***********************************************************/
 /* monitor info on PCI */
 
diff --git a/hw/pci.h b/hw/pci.h
index ce72020..5cd882c 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -268,6 +268,8 @@ int pci_device_load(PCIDevice *s, QEMUFile *f);
 
 typedef void (*pci_set_irq_fn)(void *opaque, int irq_num, int level);
 typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num);
+/* 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD */
+int pci_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin);
 PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
                          void *irq_opaque, int devfn_min, int nirq);
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 35/61] piix_pci: use pci_swizzle_map_irq_fn().
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (33 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 34/61] pci: introduce pci_swizzle_map_irq_fn() for interrupt pin swizzle Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 36/61] pci: use QLIST_ macro instead of direct list manipulation Isaku Yamahata
                   ` (29 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

use pci_swizzle_map_irq_fn().

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/piix_pci.c |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index 329aa45..87cdbd9 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -69,9 +69,7 @@ static void piix3_set_irq(void *opaque, int irq_num, int level);
    mapping. */
 static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
 {
-    int slot_addend;
-    slot_addend = (pci_dev->devfn >> 3) - 1;
-    return (irq_num + slot_addend) & 3;
+    return pci_swizzle_map_irq_fn(pci_dev, irq_num);
 }
 
 static void update_pam(PCII440FXState *d, uint32_t start, uint32_t end, int r)
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 36/61] pci: use QLIST_ macro instead of direct list manipulation.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (34 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 35/61] piix_pci: use pci_swizzle_map_irq_fn() Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 11:54   ` [Qemu-devel] " Michael S. Tsirkin
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 37/61] pci: add helper function for pci config write function to check address Isaku Yamahata
                   ` (28 subsequent siblings)
  64 siblings, 1 reply; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

For maintenance, use QLIST_ macro instead of direct list implementation
for PCIBus::next which implements singly linked list.
This patch replace it with QLIST_ macro.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |   16 +++++++---------
 1 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index b358d80..757fe7b 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -45,7 +45,7 @@ struct PCIBus {
     void *irq_opaque;
     PCIDevice *devices[256];
     PCIDevice *parent_dev;
-    PCIBus *next;
+    QLIST_ENTRY(PCIBus) next;
     /* The bus IRQ state is the logical OR of the connected devices.
        Keep a count of the number of devices with raised IRQs.  */
     int nirq;
@@ -70,7 +70,7 @@ static void pci_set_irq(void *opaque, int irq_num, int level);
 target_phys_addr_t pci_mem_base;
 static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET;
 static uint16_t pci_default_sub_device_id = PCI_SUBDEVICE_ID_QEMU;
-static PCIBus *first_bus;
+static QLIST_HEAD(, PCIBus) first_bus;
 
 static const VMStateDescription vmstate_pcibus = {
     .name = "PCIBUS",
@@ -113,8 +113,7 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
     bus->devfn_min = devfn_min;
     bus->nirq = nirq;
     bus->irq_count = qemu_mallocz(nirq * sizeof(bus->irq_count[0]));
-    bus->next = first_bus;
-    first_bus = bus;
+    QLIST_INSERT_HEAD(&first_bus, bus, next);
     vmstate_register(nbus++, &vmstate_pcibus, bus);
     qemu_register_reset(pci_bus_reset, bus);
     return bus;
@@ -129,8 +128,7 @@ static PCIBus *pci_register_secondary_bus(PCIDevice *dev,
     bus = FROM_QBUS(PCIBus, qbus_create(&pci_bus_info, &dev->qdev, name));
     bus->map_irq = map_irq;
     bus->parent_dev = dev;
-    bus->next = dev->bus->next;
-    dev->bus->next = bus;
+    QLIST_INSERT_AFTER(dev->bus, bus, next);
     return bus;
 }
 
@@ -650,7 +648,7 @@ static PCIBus *pci_find_bus_from(PCIBus *from, int bus_num)
     PCIBus *s = from;
 
     while (s && s->bus_num != bus_num)
-        s = s->next;
+        s = QLIST_NEXT(s, next);
 
     return s;
 }
@@ -1025,7 +1023,7 @@ static void pci_info_device(PCIDevice *d)
 
 void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d))
 {
-    PCIBus *bus = first_bus;
+    PCIBus *bus = QLIST_FIRST(&first_bus);
     PCIDevice *d;
     int devfn;
 
@@ -1129,7 +1127,7 @@ static void pci_bridge_write_config(PCIDevice *d,
 
 PCIBus *pci_find_bus(int bus_num)
 {
-    return pci_find_bus_from(first_bus, bus_num);
+    return pci_find_bus_from(QLIST_FIRST(&first_bus), bus_num);
 }
 
 PCIDevice *pci_find_device(int bus_num, int slot, int function)
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 37/61] pci: add helper function for pci config write function to check address.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (35 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 36/61] pci: use QLIST_ macro instead of direct list manipulation Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 11:50   ` [Qemu-devel] " Michael S. Tsirkin
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 38/61] pci: fix pci_default_write_config() Isaku Yamahata
                   ` (27 subsequent siblings)
  64 siblings, 1 reply; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

add helper function for pci config write function to check address.
Those function will be used later.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.h |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/hw/pci.h b/hw/pci.h
index 5cd882c..26c15c5 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -406,6 +406,20 @@ pci_config_get_quad(PCIDevice *d, uint32_t addr)
     return pci_get_quad(&d->config[addr]);
 }
 
+static inline int pci_config_changed(uint32_t addr, uint32_t len,
+                              uint32_t base, uint32_t end)
+{
+    /* check if [addr, addr + len] intersects [base, end] */
+    return base <= addr + len && addr <= end;
+}
+
+static inline int pci_config_changed_with_size(uint32_t addr, uint32_t len,
+                                        uint32_t base, uint32_t size)
+{
+    /* check if [addr, addr + len] intersects [base, base + size] */
+    return base <= addr + len && addr <= base + size;
+}
+
 typedef int (*pci_qdev_initfn)(PCIDevice *dev);
 typedef struct {
     DeviceInfo qdev;
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 38/61] pci: fix pci_default_write_config()
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (36 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 37/61] pci: add helper function for pci config write function to check address Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 10:44   ` [Qemu-devel] " Michael S. Tsirkin
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 39/61] pci: factor out config update logic Isaku Yamahata
                   ` (26 subsequent siblings)
  64 siblings, 1 reply; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata, Michael S. Tsirkin

When updated ROM expantion address of header type 0,
it missed to update mappings.
By using helper functions this patch also avoids memcpy() and memcmp().

Cc: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |   11 +++++------
 hw/pci.h |    9 ++++++++-
 2 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 757fe7b..2a59667 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -627,20 +627,19 @@ uint32_t pci_default_read_config(PCIDevice *d,
 
 void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
 {
-    uint8_t orig[PCI_CONFIG_SPACE_SIZE];
     int i;
     uint32_t config_size = pcie_config_size(d);
 
-    /* not efficient, but simple */
-    memcpy(orig, d->config, PCI_CONFIG_SPACE_SIZE);
     for(i = 0; i < l && addr < config_size; val >>= 8, ++i, ++addr) {
         uint8_t wmask = d->wmask[addr];
         d->config[addr] = (d->config[addr] & ~wmask) | (val & wmask);
     }
-    if (memcmp(orig + PCI_BASE_ADDRESS_0, d->config + PCI_BASE_ADDRESS_0, 24)
-        || ((orig[PCI_COMMAND] ^ d->config[PCI_COMMAND])
-            & (PCI_COMMAND_MEMORY | PCI_COMMAND_IO)))
+
+    if (pci_config_changed(addr, l,
+                           PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_5 + 4) ||
+        pci_config_changed_with_size(addr, l, PCI_ROM_ADDRESS, 4)) {
         pci_update_mappings(d);
+    }
 }
 
 static PCIBus *pci_find_bus_from(PCIBus *from, int bus_num)
diff --git a/hw/pci.h b/hw/pci.h
index 26c15c5..3327905 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -121,7 +121,12 @@ static inline int pci_bar_is_64bit(const PCIIORegion *r)
 #define  PCI_HEADER_TYPE_BRIDGE		1
 #define  PCI_HEADER_TYPE_CARDBUS	2
 #define  PCI_HEADER_TYPE_MULTI_FUNCTION 0x80
-#define PCI_BASE_ADDRESS_0	0x10	/* 32 bits */
+#define PCI_BASE_ADDRESS_0      0x10    /* 32 bits */
+#define PCI_BASE_ADDRESS_1      0x14    /* 32 bits [htype 0,1 only] */
+#define PCI_BASE_ADDRESS_2      0x18    /* 32 bits [htype 0 only] */
+#define PCI_BASE_ADDRESS_3      0x1c    /* 32 bits */
+#define PCI_BASE_ADDRESS_4      0x20    /* 32 bits */
+#define PCI_BASE_ADDRESS_5      0x24    /* 32 bits */
 #define PCI_PRIMARY_BUS		0x18	/* Primary bus number */
 #define PCI_SECONDARY_BUS	0x19	/* Secondary bus number */
 #define PCI_SEC_STATUS		0x1e	/* Secondary status register, only bit 14 used */
@@ -141,7 +146,9 @@ static inline int pci_bar_is_64bit(const PCIIORegion *r)
 #define PCI_SUBVENDOR_ID        0x2c    /* obsolete, use PCI_SUBSYSTEM_VENDOR_ID */
 #define PCI_SUBDEVICE_ID        0x2e    /* obsolete, use PCI_SUBSYSTEM_ID */
 
+#define PCI_ROM_ADDRESS         0x30    /* Bits 31..11 are address, 10..1 reserved */
 #define  PCI_ROM_ADDRESS_ENABLE 0x01
+#define PCI_ROM_ADDRESS_MASK    (~0x7ffUL)
 
 /* Bits in the PCI Status Register (PCI 2.3 spec) */
 #define PCI_STATUS_RESERVED1	0x007
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 39/61] pci: factor out config update logic.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (37 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 38/61] pci: fix pci_default_write_config() Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 40/61] pci: use qdev to get parent bus with PCIBus Isaku Yamahata
                   ` (25 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

Updating BAR in pci bar is specific to header type 00.
So split out the logic to common to header type 01 which
will be used later.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |    8 +++++++-
 1 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 2a59667..a8694f8 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -625,16 +625,22 @@ uint32_t pci_default_read_config(PCIDevice *d,
     return pcie_config_get(d, address, len);
 }
 
-void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
+static void pci_default_write_config_common(PCIDevice *d,
+                                            uint32_t addr, uint32_t val, int l)
 {
     int i;
     uint32_t config_size = pcie_config_size(d);
 
+    assert(l == 1 || l == 2 || l == 4);
     for(i = 0; i < l && addr < config_size; val >>= 8, ++i, ++addr) {
         uint8_t wmask = d->wmask[addr];
         d->config[addr] = (d->config[addr] & ~wmask) | (val & wmask);
     }
+}
 
+void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
+{
+    pci_default_write_config_common(d, addr, val, l);
     if (pci_config_changed(addr, l,
                            PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_5 + 4) ||
         pci_config_changed_with_size(addr, l, PCI_ROM_ADDRESS, 4)) {
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 40/61] pci: use qdev to get parent bus with PCIBus.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (38 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 39/61] pci: factor out config update logic Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 41/61] pci: make bar update function aware of pci bridge Isaku Yamahata
                   ` (24 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

Now qdev tracks the relationship between bus and device, so
a member, bus, in PCIDevice/PCIBridge and parent_dev in PCIBus
are redundant.
This patch removes them and introduces some helper functions
which will be used later.

For non-qdevfied device, keep the bus member in PCIDevice.
It will be removed once all of PCIDevices are converted.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci-hotplug.c |    7 ++---
 hw/pci.c         |   69 +++++++++++++++++++++++++++++++++++++++++++-----------
 hw/pci.h         |    8 +++++-
 3 files changed, 65 insertions(+), 19 deletions(-)

diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index f3dc421..1aa1241 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -181,11 +181,10 @@ void pci_device_hot_add(Monitor *mon, const QDict *qdict)
         monitor_printf(mon, "invalid type: %s\n", type);
 
     if (dev) {
-        qemu_system_device_hot_add(pci_bus_num(dev->bus),
-                                   PCI_SLOT(dev->devfn), 1);
+        int bus_num = pci_bus_num(pci_get_parent_bus(dev));
+        qemu_system_device_hot_add(bus_num, PCI_SLOT(dev->devfn), 1);
         monitor_printf(mon, "OK domain %d, bus %d, slot %d, function %d\n",
-                       0, pci_bus_num(dev->bus), PCI_SLOT(dev->devfn),
-                       PCI_FUNC(dev->devfn));
+                       0, bus_num, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
     } else
         monitor_printf(mon, "failed to add %s\n", opts);
 }
diff --git a/hw/pci.c b/hw/pci.c
index a8694f8..ec6c7d4 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -44,7 +44,6 @@ struct PCIBus {
     uint32_t config_reg; /* XXX: suppress */
     void *irq_opaque;
     PCIDevice *devices[256];
-    PCIDevice *parent_dev;
     QLIST_ENTRY(PCIBus) next;
     /* The bus IRQ state is the logical OR of the connected devices.
        Keep a count of the number of devices with raised IRQs.  */
@@ -84,6 +83,37 @@ static const VMStateDescription vmstate_pcibus = {
     }
 };
 
+static PCIBus *qbus_to_pcibus(struct BusState *qbus)
+{
+    return DO_UPCAST(PCIBus, qbus, qbus);
+}
+
+PCIDevice *qdev_to_pcidev(struct DeviceState *qdev)
+{
+    return DO_UPCAST(PCIDevice, qdev, qdev);
+}
+
+PCIBus *pci_get_parent_bus(PCIDevice *dev)
+{
+    if (dev->qdev.info == NULL) {
+        /* for non-qdevfied device */
+        assert(dev->bus != NULL);
+        return dev->bus;
+    }
+
+    return qbus_to_pcibus(dev->qdev.parent_bus);
+}
+
+BusState *pci_bus_to_qbus(PCIBus *bus)
+{
+    return &bus->qbus;
+}
+
+PCIDevice *pci_bus_to_dev(PCIBus *bus)
+{
+    return qdev_to_pcidev(bus->qbus.parent);
+}
+
 static void pci_bus_reset(void *opaque)
 {
     PCIBus *bus = opaque;
@@ -127,7 +157,6 @@ static PCIBus *pci_register_secondary_bus(PCIDevice *dev,
 
     bus = FROM_QBUS(PCIBus, qbus_create(&pci_bus_info, &dev->qdev, name));
     bus->map_irq = map_irq;
-    bus->parent_dev = dev;
     QLIST_INSERT_AFTER(dev->bus, bus, next);
     return bus;
 }
@@ -379,7 +408,6 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
     } else if (bus->devices[devfn]) {
         return NULL;
     }
-    pci_dev->bus = bus;
     pci_dev->devfn = devfn;
     pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
     memset(pci_dev->irq_state, 0, sizeof(pci_dev->irq_state));
@@ -410,6 +438,8 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name,
     pci_dev = qemu_mallocz(instance_size);
     pci_dev = do_pci_register_device(pci_dev, bus, name, devfn,
                                      config_read, config_write);
+    /* XXX for non-qdevfied device */
+    pci_dev->bus = bus;
     return pci_dev;
 }
 static target_phys_addr_t pci_to_cpu_addr(target_phys_addr_t addr)
@@ -448,7 +478,7 @@ int pci_unregister_device(PCIDevice *pci_dev)
     pci_unregister_io_regions(pci_dev);
 
     qemu_free_irqs(pci_dev->irq);
-    pci_dev->bus->devices[pci_dev->devfn] = NULL;
+    pci_get_parent_bus(pci_dev)->devices[pci_dev->devfn] = NULL;
     qdev_free(&pci_dev->qdev);
     return 0;
 }
@@ -891,11 +921,11 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
 
     pci_dev->irq_state[irq_num] = level;
     for (;;) {
-        bus = pci_dev->bus;
+        bus = pci_get_parent_bus(pci_dev);
         irq_num = bus->map_irq(pci_dev, irq_num);
         if (bus->set_irq)
             break;
-        pci_dev = bus->parent_dev;
+        pci_dev = pci_bus_to_dev(bus);
     }
     bus->irq_count[irq_num] += change;
     bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
@@ -963,7 +993,8 @@ static void pci_info_device(PCIDevice *d)
     const pci_class_desc *desc;
 
     monitor_printf(mon, "  Bus %2d, device %3d, function %d:\n",
-                   d->bus->bus_num, PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
+                   pci_get_parent_bus(d)->bus_num,
+                   PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
     class = le16_to_cpu(*((uint16_t *)(d->config + PCI_CLASS_DEVICE)));
     monitor_printf(mon, "    ");
     desc = pci_class_descriptions;
@@ -1118,16 +1149,27 @@ PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
 
 typedef struct {
     PCIDevice dev;
-    PCIBus *bus;
 } PCIBridge;
 
+static PCIBridge *pci_dev_to_br(PCIDevice *d)
+{
+    return DO_UPCAST(PCIBridge, dev, d);
+}
+
+static PCIBus *pci_bridge_get_secbus(PCIBridge *bridge)
+{
+    /* assuming only one bus is registered */
+    return qbus_to_pcibus(QLIST_FIRST(&bridge->dev.qdev.child_bus));
+}
+
 static void pci_bridge_write_config(PCIDevice *d,
                              uint32_t address, uint32_t val, int len)
 {
-    PCIBridge *s = (PCIBridge *)d;
+    PCIBridge *bridge = pci_dev_to_br(d);
+    PCIBus *bus = pci_bridge_get_secbus(bridge);
 
     pci_default_write_config(d, address, val, len);
-    s->bus->bus_num = d->config[PCI_SECONDARY_BUS];
+    bus->bus_num = d->config[PCI_SECONDARY_BUS];
 }
 
 PCIBus *pci_find_bus(int bus_num)
@@ -1167,8 +1209,7 @@ PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
         PCI_HEADER_TYPE_MULTI_FUNCTION | PCI_HEADER_TYPE_BRIDGE; // header_type
     s->dev.config[0x1E] = 0xa0; // secondary status
 
-    s->bus = pci_register_secondary_bus(&s->dev, map_irq, name);
-    return s->bus;
+    return pci_register_secondary_bus(&s->dev, map_irq, name);
 }
 
 static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
@@ -1315,8 +1356,8 @@ static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent)
 
     monitor_printf(mon, "%*sclass %s, addr %02x:%02x.%x, "
                    "pci id %04x:%04x (sub %04x:%04x)\n",
-                   indent, "", ctxt,
-                   d->bus->bus_num, PCI_SLOT(d->devfn), PCI_FUNC(d->devfn),
+                   indent, "", ctxt, pci_get_parent_bus(d)->bus_num,
+                   PCI_SLOT(d->devfn), PCI_FUNC(d->devfn),
                    le16_to_cpu(*((uint16_t *)(d->config + PCI_VENDOR_ID))),
                    le16_to_cpu(*((uint16_t *)(d->config + PCI_DEVICE_ID))),
                    le16_to_cpu(*((uint16_t *)(d->config + PCI_SUBSYSTEM_VENDOR_ID))),
diff --git a/hw/pci.h b/hw/pci.h
index 3327905..0aedbf5 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -204,7 +204,9 @@ struct PCIDevice {
     uint8_t *used;
 
     /* the following fields are read only */
-    PCIBus *bus;
+    PCIBus *bus;     /* non qdevfied device only
+                      * Once all the device is qdevified, this will be removed.
+                      */
     uint32_t devfn;
     char name[64];
     PCIIORegion io_regions[PCI_NUM_REGIONS];
@@ -291,6 +293,10 @@ int pci_bus_num(PCIBus *s);
 void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d));
 PCIBus *pci_find_bus(int bus_num);
 PCIDevice *pci_find_device(int bus_num, int slot, int function);
+PCIBus *pci_get_parent_bus(PCIDevice *dev);
+PCIDevice *qdev_to_pcidev(struct DeviceState *qdev);
+BusState *pci_bus_to_qbus(PCIBus *bus);
+PCIDevice *pci_bus_to_dev(PCIBus *bus);
 
 int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
                      unsigned *slotp);
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 41/61] pci: make bar update function aware of pci bridge.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (39 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 40/61] pci: use qdev to get parent bus with PCIBus Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 42/61] pci/brdige: qdevfy and initialize secondary bus and subordinate bus Isaku Yamahata
                   ` (23 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

header type of 01 has differenct BAR to type 00.
It has only BAR0,1 and expantion rom whose offset address
is different from type 00 one.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |   55 +++++++++++++++++++++++++++++++++++++++++++------------
 hw/pci.h |    3 +++
 2 files changed, 46 insertions(+), 12 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index ec6c7d4..dc93b28 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -483,6 +483,35 @@ int pci_unregister_device(PCIDevice *pci_dev)
     return 0;
 }
 
+#define PCI_BAR_INVALID  UINT32_MAX
+static uint32_t pci_bar_config_offset(PCIDevice *d, int region_num)
+{
+    switch (d->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION) {
+    case PCI_HEADER_TYPE_NORMAL:
+        /* BAR 0-5 and Expantion ROM*/
+        if (region_num < PCI_ROM_SLOT) {
+            return PCI_BASE_ADDRESS_0 + region_num * 4;
+        } else if (region_num == PCI_ROM_SLOT) {
+            return PCI_ROM_ADDRESS;
+        }
+        break;
+    case PCI_HEADER_TYPE_BRIDGE:
+        /* BAR 0-1 and Expantion ROM */
+        if (region_num < 2) {
+            return PCI_BASE_ADDRESS_0 + region_num * 4;
+        } else if (region_num == PCI_ROM_SLOT) {
+            return PCI_ROM_ADDRESS1;
+        }
+        break;
+    case PCI_HEADER_TYPE_CARDBUS:
+    default:
+        break;
+    }
+    fprintf(stderr, "ERROR: %s: unknow PCI config header type %d or bar %d\n",
+            __func__, d->config[PCI_HEADER_TYPE], region_num);
+    return PCI_BAR_INVALID;
+}
+
 void pci_register_bar(PCIDevice *pci_dev, int region_num,
                             uint64_t size, int type,
                             PCIMapIORegionFunc *map_func)
@@ -506,13 +535,11 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
     r->type = type;
     r->map_func = map_func;
 
+    addr = pci_bar_config_offset(pci_dev, region_num);
     wmask = ~(size - 1);
     if (region_num == PCI_ROM_SLOT) {
-        addr = 0x30;
         /* ROM enable bit is writeable */
         wmask |= PCI_ROM_ADDRESS_ENABLE;
-    } else {
-        addr = 0x10 + region_num * 4;
     }
 
     *(uint32_t *)(pci_dev->config + addr) = cpu_to_le32(type);
@@ -541,11 +568,7 @@ static void pci_update_mappings(PCIDevice *d)
         if (r->size == 0)
             continue;
 
-        if (i == PCI_ROM_SLOT) {
-            config_ofs = 0x30;
-        } else {
-            config_ofs = 0x10 + i * 4;
-        }
+        config_ofs = pci_bar_config_offset(d, i);
 
         if (pci_bar_is_64bit(r)) {
             bar = le64_to_cpu(*(uint64_t *)(d->config + config_ofs));
@@ -1165,11 +1188,19 @@ static PCIBus *pci_bridge_get_secbus(PCIBridge *bridge)
 static void pci_bridge_write_config(PCIDevice *d,
                              uint32_t address, uint32_t val, int len)
 {
-    PCIBridge *bridge = pci_dev_to_br(d);
-    PCIBus *bus = pci_bridge_get_secbus(bridge);
+    pci_default_write_config_common(d, address, val, len);
+
+    if (pci_config_changed(address, len,
+                           PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_2 + 4) ||
+        pci_config_changed_with_size(address, len, PCI_ROM_ADDRESS1, 4)) {
+        pci_update_mappings(d);
+    }
+    if (pci_config_changed_with_size(address, len, PCI_SECONDARY_BUS, 1)) {
+        PCIBridge *bridge = pci_dev_to_br(d);
+        PCIBus *bus = pci_bridge_get_secbus(bridge);
 
-    pci_default_write_config(d, address, val, len);
-    bus->bus_num = d->config[PCI_SECONDARY_BUS];
+        bus->bus_num = d->config[PCI_SECONDARY_BUS];
+    }
 }
 
 PCIBus *pci_find_bus(int bus_num)
diff --git a/hw/pci.h b/hw/pci.h
index 0aedbf5..b279f2d 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -170,6 +170,9 @@ static inline int pci_bar_is_64bit(const PCIIORegion *r)
 
 #define PCI_COMMAND_RESERVED_MASK_HI (PCI_COMMAND_RESERVED >> 8)
 
+/* Header type 1 (PCI-to-PCI bridges) */
+#define PCI_ROM_ADDRESS1        0x38    /* Same as PCI_ROM_ADDRESS, but for htype 1 */
+
 /* Size of the standard PCI config header */
 #define PCI_CONFIG_HEADER_SIZE 0x40
 /* Size of the standard PCI config space */
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 42/61] pci/brdige: qdevfy and initialize secondary bus and subordinate bus.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (40 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 41/61] pci: make bar update function aware of pci bridge Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 43/61] pci: add helper function to initialize wmask Isaku Yamahata
                   ` (22 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

qdevfy pci bridge, and
initialize secondary bus and subordinate bus in configuration space.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/apb_pci.c |   10 +++--
 hw/pci.c     |  112 ++++++++++++++++++++++++++++++++++++++++++++--------------
 hw/pci.h     |   13 +++++++
 3 files changed, 104 insertions(+), 31 deletions(-)

diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index c2fe5bf..f679847 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -252,12 +252,14 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
                                          0, 32);
     pci_create_simple(d->host_state.bus, 0, "pbm");
     /* APB secondary busses */
-    *bus2 = pci_bridge_init(d->host_state.bus, 8, PCI_VENDOR_ID_SUN,
+    *bus2 = pci_bridge_init(d->host_state.bus,
+                            PCI_DEVFN(1, 0), PCI_VENDOR_ID_SUN,
                             PCI_DEVICE_ID_SUN_SIMBA, pci_apb_map_irq,
-                            "Advanced PCI Bus secondary bridge 1");
-    *bus3 = pci_bridge_init(d->host_state.bus, 9, PCI_VENDOR_ID_SUN,
+                            "Advanced PCI Bus Secondary bridge 1");
+    *bus3 = pci_bridge_init(d->host_state.bus,
+                            PCI_DEVFN(1, 1), PCI_VENDOR_ID_SUN,
                             PCI_DEVICE_ID_SUN_SIMBA, pci_apb_map_irq,
-                            "Advanced PCI Bus secondary bridge 2");
+                            "Advanced PCI Bus Secondary bridge 2");
 
     return d->host_state.bus;
 }
diff --git a/hw/pci.c b/hw/pci.c
index dc93b28..7a158db 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -129,12 +129,17 @@ static void pci_bus_reset(void *opaque)
     }
 }
 
+static int pci_bus_get_instance_id(void)
+{
+    static int nbus = 0;
+    return nbus++;
+}
+
 PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
                          void *irq_opaque, int devfn_min, int nirq)
 {
     PCIBus *bus;
-    static int nbus = 0;
 
     bus = FROM_QBUS(PCIBus, qbus_create(&pci_bus_info, parent, name));
     bus->set_irq = set_irq;
@@ -144,20 +149,24 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
     bus->nirq = nirq;
     bus->irq_count = qemu_mallocz(nirq * sizeof(bus->irq_count[0]));
     QLIST_INSERT_HEAD(&first_bus, bus, next);
-    vmstate_register(nbus++, &vmstate_pcibus, bus);
+    vmstate_register(pci_bus_get_instance_id(), &vmstate_pcibus, bus);
     qemu_register_reset(pci_bus_reset, bus);
     return bus;
 }
 
-static PCIBus *pci_register_secondary_bus(PCIDevice *dev,
-                                          pci_map_irq_fn map_irq,
-                                          const char *name)
+PCIBus *pci_register_secondary_bus(PCIDevice *dev, pci_map_irq_fn map_irq,
+                                   const char* name, int devfn_min)
 {
     PCIBus *bus;
 
     bus = FROM_QBUS(PCIBus, qbus_create(&pci_bus_info, &dev->qdev, name));
+
     bus->map_irq = map_irq;
-    QLIST_INSERT_AFTER(dev->bus, bus, next);
+    bus->bus_num = dev->config[PCI_SECONDARY_BUS];
+    bus->devfn_min = devfn_min;
+
+    QLIST_INSERT_AFTER(pci_get_parent_bus(dev), bus, next);
+    vmstate_register(pci_bus_get_instance_id(), &vmstate_pcibus, bus);
     return bus;
 }
 
@@ -1185,7 +1194,7 @@ static PCIBus *pci_bridge_get_secbus(PCIBridge *bridge)
     return qbus_to_pcibus(QLIST_FIRST(&bridge->dev.qdev.child_bus));
 }
 
-static void pci_bridge_write_config(PCIDevice *d,
+void pci_bridge_write_config(PCIDevice *d,
                              uint32_t address, uint32_t val, int len)
 {
     pci_default_write_config_common(d, address, val, len);
@@ -1218,29 +1227,78 @@ PCIDevice *pci_find_device(int bus_num, int slot, int function)
     return bus->devices[PCI_DEVFN(slot, function)];
 }
 
-PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
-                        pci_map_irq_fn map_irq, const char *name)
+int pci_bridge_initfn(PCIDevice *pci_dev)
 {
-    PCIBridge *s;
-    s = (PCIBridge *)pci_register_device(bus, name, sizeof(PCIBridge),
-                                         devfn, NULL, pci_bridge_write_config);
-
-    pci_config_set_vendor_id(s->dev.config, vid);
-    pci_config_set_device_id(s->dev.config, did);
-
-    s->dev.config[0x04] = 0x06; // command = bus master, pci mem
-    s->dev.config[0x05] = 0x00;
-    s->dev.config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
-    s->dev.config[0x07] = 0x00; // status = fast devsel
-    s->dev.config[0x08] = 0x00; // revision
-    s->dev.config[0x09] = 0x00; // programming i/f
-    pci_config_set_class(s->dev.config, PCI_CLASS_BRIDGE_PCI);
-    s->dev.config[0x0D] = 0x10; // latency_timer
-    s->dev.config[PCI_HEADER_TYPE] =
+    uint8_t *pci_conf;
+
+    pci_conf = pci_dev->config;
+    pci_conf[0x04] = 0x06; // command = bus master, pci mem
+    pci_conf[0x05] = 0x00;
+    pci_conf[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
+    pci_conf[0x07] = 0x00; // status = fast devsel
+    pci_conf[0x08] = 0x00; // revision
+    pci_conf[0x09] = 0x00; // programming i/f
+    pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_PCI);
+    pci_conf[0x0D] = 0x10; // latency_timer
+    pci_conf[PCI_HEADER_TYPE] =
         PCI_HEADER_TYPE_MULTI_FUNCTION | PCI_HEADER_TYPE_BRIDGE; // header_type
-    s->dev.config[0x1E] = 0xa0; // secondary status
+    pci_conf[0x18] = pci_get_parent_bus(pci_dev)->bus_num;// primary bus number
+    /* secondary bus and subordinate bus will be set by the caller */
+    pci_conf[0x1E] = 0xa0; // secondary status
+
+    /* vid/did will be set later */
+
+    return 0;
+}
+
+#define PCI_BRIDGE_DEFAULT      "default PCI to PCI bridge"
+static PCIDeviceInfo pci_bridge_info_default = {
+    .qdev.name = PCI_BRIDGE_DEFAULT,
+    .qdev.size = sizeof(PCIBridge),
+    .config_write = pci_bridge_write_config,
+    .init = pci_bridge_initfn,
+    .pcie = 0,
+};
 
-    return pci_register_secondary_bus(&s->dev, map_irq, name);
+static void pci_bridge_register_device(void)
+{
+    pci_qdev_register(&pci_bridge_info_default);
+}
+device_init(pci_bridge_register_device);
+
+PCIBus *pci_bridge_create_simple(PCIBus *bus, int devfn, uint16_t vid,
+                                 uint16_t did, int sec_bus, int sub_bus,
+                                 pci_map_irq_fn map_irq, const char *bus_name,
+                                 const char *name)
+{
+    DeviceState *qdev;
+    uint8_t* pci_conf;
+    PCIDevice *d;
+
+    qdev = qdev_create(&bus->qbus, name);
+
+    qdev_prop_set_uint32(qdev, "addr", devfn);
+
+    qdev_init(qdev);
+
+    d = qdev_to_pcidev(qdev);
+    pci_conf = d->config;
+    pci_config_set_vendor_id(pci_conf, vid);
+    pci_config_set_device_id(pci_conf, did);
+
+    assert(sec_bus <= sub_bus);
+    pci_config_set_byte(d, PCI_SECONDARY_BUS, sec_bus);
+    pci_config_set_byte(d, PCI_SUBORDINATE_BUS, sub_bus);
+
+    return pci_register_secondary_bus(d, map_irq, bus_name, 0);
+}
+
+PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid,
+                        uint16_t did,
+                        pci_map_irq_fn map_irq, const char *name)
+{
+    return pci_bridge_create_simple(bus, devfn, vid, did, 0, 0,
+                                    map_irq, name, PCI_BRIDGE_DEFAULT);
 }
 
 static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
diff --git a/hw/pci.h b/hw/pci.h
index b279f2d..017ca07 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -172,6 +172,8 @@ static inline int pci_bar_is_64bit(const PCIIORegion *r)
 
 /* Header type 1 (PCI-to-PCI bridges) */
 #define PCI_ROM_ADDRESS1        0x38    /* Same as PCI_ROM_ADDRESS, but for htype 1 */
+#define PCI_SUBORDINATE_BUS     0x1a    /* Highest bus number behind the bridge */
+
 
 /* Size of the standard PCI config header */
 #define PCI_CONFIG_HEADER_SIZE 0x40
@@ -285,6 +287,8 @@ int pci_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin);
 PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
                          void *irq_opaque, int devfn_min, int nirq);
+PCIBus *pci_register_secondary_bus(PCIDevice *dev, pci_map_irq_fn map_irq,
+                                   const char* name, int devfn_min);
 
 PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
                         const char *default_devaddr);
@@ -307,6 +311,15 @@ int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
 void pci_info(Monitor *mon);
 PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
                         pci_map_irq_fn map_irq, const char *name);
+PCIBus *pci_bridge_create_simple(PCIBus *bus, int devfn, uint16_t vid,
+                                 uint16_t did, int sec_bus, int sub_bus,
+                                 pci_map_irq_fn map_irq, const char *bus_name,
+                                 const char *name);
+void pci_bridge_write_config(PCIDevice *d,
+                             uint32_t address, uint32_t val, int len);
+int pci_bridge_initfn(PCIDevice *pci_dev);
+void pci_bridge_set_map_irq(PCIBus *bus, pci_map_irq_fn map_irq);
+
 
 static inline void
 pci_set_byte(uint8_t *config, uint8_t val)
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 43/61] pci: add helper function to initialize wmask.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (41 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 42/61] pci/brdige: qdevfy and initialize secondary bus and subordinate bus Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 44/61] pci: initialize wmask according to pci header type Isaku Yamahata
                   ` (21 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

add helper function to initialize wmask.
This will be used later.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |   25 +++++++++++++++++++++++++
 hw/pci.h |    4 ++++
 2 files changed, 29 insertions(+), 0 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 7a158db..335ab5f 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -401,6 +401,31 @@ static void pci_config_init(PCIDevice *pci_dev)
     PCI_CONFIG_ALLOC(pci_dev, used, config_size);
 }
 
+static void pci_conf_init(PCIDevice *d, uint32_t addr, uint32_t wmask, int len)
+{
+    int i;
+
+    for (i = 0; i < len; i++) {
+        d->wmask[addr + i] = wmask & 0xff;
+        wmask >>= 8;
+    }
+}
+
+void pci_conf_initb(PCIDevice *d, uint32_t addr, uint32_t wmask)
+{
+    pci_conf_init(d, addr, wmask, 1);
+}
+
+void pci_conf_initw(PCIDevice *d, uint32_t addr, uint32_t wmask)
+{
+    pci_conf_init(d, addr, wmask, 2);
+}
+
+void pci_conf_initl(PCIDevice *d, uint32_t addr, uint32_t wmask)
+{
+    pci_conf_init(d, addr, wmask, 4);
+}
+
 /* -1 for devfn means auto assign */
 static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
                                          const char *name, int devfn,
diff --git a/hw/pci.h b/hw/pci.h
index 017ca07..e1d8564 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -254,6 +254,10 @@ struct PCIDevice {
     target_phys_addr_t msix_page_size;
 };
 
+void pci_conf_initb(PCIDevice *d, uint32_t addr, uint32_t wmask);
+void pci_conf_initw(PCIDevice *d, uint32_t addr, uint32_t wmask);
+void pci_conf_initl(PCIDevice *d, uint32_t addr, uint32_t wmask);
+
 PCIDevice *pci_register_device(PCIBus *bus, const char *name,
                                int instance_size, int devfn,
                                PCIConfigReadFunc *config_read,
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 44/61] pci: initialize wmask according to pci header type.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (42 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 43/61] pci: add helper function to initialize wmask Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 45/61] pci/monitor: print out bridge's filtering values and so on Isaku Yamahata
                   ` (20 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

- initialize wmask according to pci header type.
  So far, header of type 01  was not correctly initialized.
- only sets default subsystem id for header type 00.
  header type 01 doesn't have subsystem id, and uses the register
  for other purpose. So setting default subsystem id doesn't make sense.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/cirrus_vga.c |    2 +-
 hw/pci.c        |  182 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
 hw/pci.h        |   64 +++++++++++++++++++-
 3 files changed, 241 insertions(+), 7 deletions(-)

diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 5103763..f4a16d4 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -180,7 +180,7 @@
 #define PCI_COMMAND_PALETTESNOOPING         0x0020
 #define PCI_COMMAND_PARITYDETECTION         0x0040
 #define PCI_COMMAND_ADDRESSDATASTEPPING     0x0080
-#define PCI_COMMAND_SERR                    0x0100
+// #define PCI_COMMAND_SERR                    0x0100 /* duplicated */
 #define PCI_COMMAND_BACKTOBACKTRANS         0x0200
 // PCI 0x08, 0xff000000 (0x09-0x0b:class,0x08:rev)
 #define PCI_CLASS_BASE_DISPLAY        0x03
diff --git a/hw/pci.c b/hw/pci.c
index 335ab5f..94fe87f 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -426,11 +426,86 @@ void pci_conf_initl(PCIDevice *d, uint32_t addr, uint32_t wmask)
     pci_conf_init(d, addr, wmask, 4);
 }
 
+static void pci_conf_init_type_00_default(PCIDevice *d)
+{
+    uint32_t addr;
+
+    pci_set_default_subsystem_id(d);
+
+    /* Vendor ID, Device ID: read only */
+    pci_conf_initw(d, PCI_VENDOR_ID, 0);
+    pci_conf_initw(d, PCI_DEVICE_ID, 0);
+
+    pci_conf_initw(d, PCI_COMMAND,
+                   PCI_COMMAND_IO |
+                   PCI_COMMAND_MEMORY |
+                   PCI_COMMAND_MASTER |
+                   PCI_COMMAND_SPECIAL |
+                   PCI_COMMAND_INVALIDATE |
+                   PCI_COMMAND_VGA_PALETTE |
+                   PCI_COMMAND_PARITY |
+                   PCI_COMMAND_WAIT |
+                   PCI_COMMAND_SERR |
+                   PCI_COMMAND_FAST_BACK |
+                   PCI_COMMAND_INTX_DISABLE);
+
+    /* nothing is emulated at this moment */
+    pci_conf_initw(d, PCI_STATUS, 0);
+
+    /* revision id, class code: read only */
+    pci_conf_initb(d, PCI_REVISION_ID, 0);
+    pci_conf_initb(d, PCI_CLASS_PROG, 0);
+    pci_conf_initw(d, PCI_CLASS_DEVICE, 0);
+
+    pci_conf_initb(d, PCI_CACHE_LINE_SIZE, ~0);
+    pci_conf_initb(d, PCI_LATENCY_TIMER, ~0);
+
+    /* header type: read only */
+    pci_conf_initb(d, PCI_HEADER_TYPE, 0);
+
+    /* BIST emulation isn't implemented */
+    pci_conf_initb(d, PCI_BIST, 0);
+
+    /* bar:wmask will be updated by pci_register_bar() */
+    pci_conf_initl(d, PCI_BASE_ADDRESS_0, 0);
+    pci_conf_initl(d, PCI_BASE_ADDRESS_1, 0);
+    pci_conf_initl(d, PCI_BASE_ADDRESS_2, 0);
+    pci_conf_initl(d, PCI_BASE_ADDRESS_3, 0);
+    pci_conf_initl(d, PCI_BASE_ADDRESS_4, 0);
+    pci_conf_initl(d, PCI_BASE_ADDRESS_5, 0);
+
+    /* not card bus*/
+    pci_conf_initl(d, PCI_CARDBUS_CIS, 0);
+
+    /* Subsystem ID, Subsystem Vendor ID: read only*/
+    pci_conf_initw(d, PCI_SUBSYSTEM_VENDOR_ID, 0);
+    pci_conf_initw(d, PCI_SUBSYSTEM_ID, 0);
+
+
+    /* mask will be updated by pci_register_bar() */
+    pci_conf_initl(d, PCI_ROM_ADDRESS, 0);
+
+    pci_conf_initb(d, PCI_CAPABILITY_LIST, 0);
+
+    /* offset 0x35 ... 0x3d are reserved so is read only */
+
+    pci_conf_initb(d, PCI_INTERRUPT_LINE, ~0);
+    pci_conf_initb(d, PCI_INTERRUPT_PIN, 0);
+    pci_conf_initb(d, PCI_MIN_GNT, 0);
+    pci_conf_initb(d, PCI_MAX_LAT, 0);
+
+    /* device dependent part */
+    for (addr = PCI_CONFIG_HEADER_SIZE; addr < PCI_CONFIG_SPACE_SIZE; addr++)
+        pci_conf_initb(d, addr, ~0);
+}
+
 /* -1 for devfn means auto assign */
+typedef void (*pci_conf_init_t)(PCIDevice *d);
 static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
                                          const char *name, int devfn,
                                          PCIConfigReadFunc *config_read,
-                                         PCIConfigWriteFunc *config_write)
+                                         PCIConfigWriteFunc *config_write,
+                                         pci_conf_init_t conf_init)
 {
     if (devfn < 0) {
         for(devfn = bus->devfn_min ; devfn < 256; devfn += 8) {
@@ -446,9 +521,9 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
     pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
     memset(pci_dev->irq_state, 0, sizeof(pci_dev->irq_state));
     pci_config_init(pci_dev);
-    pci_set_default_subsystem_id(pci_dev);
     pci_init_cmask(pci_dev);
     pci_init_wmask(pci_dev);
+    conf_init(pci_dev);
 
     if (!config_read)
         config_read = pci_default_read_config;
@@ -471,11 +546,15 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name,
 
     pci_dev = qemu_mallocz(instance_size);
     pci_dev = do_pci_register_device(pci_dev, bus, name, devfn,
-                                     config_read, config_write);
-    /* XXX for non-qdevfied device */
+                                     config_read, config_write,
+                                     pci_conf_init_type_00_default);
+
+    /* XXX for non-qdevfied device
+       Once all pci device is qdevfied this function will disapear */
     pci_dev->bus = bus;
     return pci_dev;
 }
+
 static target_phys_addr_t pci_to_cpu_addr(target_phys_addr_t addr)
 {
     return addr + pci_mem_base;
@@ -1252,6 +1331,83 @@ PCIDevice *pci_find_device(int bus_num, int slot, int function)
     return bus->devices[PCI_DEVFN(slot, function)];
 }
 
+static void pci_conf_init_type_01_default(PCIDevice *d)
+{
+    uint32_t addr;
+
+    /* Vendor ID, Device ID: read only */
+    pci_conf_initw(d, PCI_VENDOR_ID, 0);
+    pci_conf_initw(d, PCI_DEVICE_ID, 0);
+
+    pci_conf_initw(d, PCI_COMMAND,
+                   PCI_COMMAND_IO |
+                   PCI_COMMAND_MEMORY |
+                   PCI_COMMAND_MASTER |
+                   PCI_COMMAND_SPECIAL |
+                   PCI_COMMAND_INVALIDATE |
+                   PCI_COMMAND_VGA_PALETTE |
+                   PCI_COMMAND_PARITY |
+                   PCI_COMMAND_WAIT |
+                   PCI_COMMAND_SERR |
+                   PCI_COMMAND_FAST_BACK |
+                   PCI_COMMAND_INTX_DISABLE);
+
+    /* nothing is emulated at this moment */
+    pci_conf_initw(d, PCI_STATUS, 0);
+
+    /* revision id, class code: read only */
+    pci_conf_initb(d, PCI_REVISION_ID, 0);
+    pci_conf_initb(d, PCI_CLASS_PROG, 0);
+    pci_conf_initw(d, PCI_CLASS_DEVICE, 0);
+
+    pci_conf_initb(d, PCI_CACHE_LINE_SIZE, ~0);
+    pci_conf_initb(d, PCI_LATENCY_TIMER, ~0);
+
+    /* header type: read only */
+    pci_conf_initb(d, PCI_HEADER_TYPE, 0);
+
+    /* BIST emulation isn't implemented */
+    pci_conf_initb(d, PCI_BIST, 0);
+
+    /* bar:wmask will be updated by pci_register_bar() */
+    pci_conf_initl(d, PCI_BASE_ADDRESS_0, 0);
+    pci_conf_initl(d, PCI_BASE_ADDRESS_1, 0);
+
+    pci_conf_initb(d, PCI_PRIMARY_BUS, ~0);
+    pci_conf_initb(d, PCI_SECONDARY_BUS, ~0);
+    pci_conf_initb(d, PCI_SUBORDINATE_BUS, ~0);
+    pci_conf_initb(d, PCI_SEC_LATENCY_TIMER, ~0);
+    pci_conf_initb(d, PCI_IO_BASE, PCI_IO_RANGE_MASK & 0xff);
+    pci_conf_initb(d, PCI_IO_LIMIT, PCI_IO_RANGE_MASK & 0xff);
+
+    /* sec status isn't emulated (yet) */
+    pci_conf_initw(d, PCI_SEC_STATUS, 0);
+
+    pci_conf_initw(d, PCI_MEMORY_BASE, PCI_MEMORY_RANGE_MASK & 0xffff);
+    pci_conf_initw(d, PCI_MEMORY_LIMIT, PCI_MEMORY_RANGE_MASK & 0xffff);
+    pci_conf_initw(d, PCI_PREF_MEMORY_BASE, PCI_PREF_RANGE_MASK & 0xffff);
+    pci_conf_initw(d, PCI_PREF_MEMORY_LIMIT, PCI_PREF_RANGE_MASK & 0xffff);
+    pci_conf_initl(d, PCI_PREF_BASE_UPPER32, ~0);
+    pci_conf_initl(d, PCI_PREF_LIMIT_UPPER32, ~0);
+
+    /* only support 64K io port */
+    pci_conf_initw(d, PCI_IO_BASE_UPPER16, 0);
+    pci_conf_initw(d, PCI_IO_LIMIT_UPPER16, 0);
+
+    pci_conf_initb(d, PCI_CAPABILITY_LIST, 0);
+
+    /* wmask will be updated by pci_register_bar() */
+    pci_conf_initl(d, PCI_ROM_ADDRESS1, 0);
+
+    pci_conf_initb(d, PCI_INTERRUPT_LINE, ~0);
+    pci_conf_initb(d, PCI_INTERRUPT_PIN, 0);
+    pci_conf_initw(d, PCI_BRIDGE_CONTROL, ~0);
+
+    /* device dependent part */
+    for (addr = PCI_CONFIG_HEADER_SIZE; addr < PCI_CONFIG_SPACE_SIZE; addr++)
+        pci_conf_initb(d, addr, ~0);
+}
+
 int pci_bridge_initfn(PCIDevice *pci_dev)
 {
     uint8_t *pci_conf;
@@ -1326,6 +1482,21 @@ PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid,
                                     map_irq, name, PCI_BRIDGE_DEFAULT);
 }
 
+static pci_conf_init_t pci_get_config_initfn(uint8_t header_type)
+{
+    switch (header_type & ~PCI_HEADER_TYPE_MULTI_FUNCTION) {
+    case PCI_HEADER_TYPE_NORMAL:
+        return pci_conf_init_type_00_default;
+    case PCI_HEADER_TYPE_BRIDGE:
+        return pci_conf_init_type_01_default;
+    case PCI_HEADER_TYPE_CARDBUS:
+    default:
+        abort();
+        break;
+    }
+    /* NOTREACHED */
+}
+
 static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
 {
     PCIDevice *pci_dev = (PCIDevice *)qdev;
@@ -1336,7 +1507,8 @@ static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
     bus = FROM_QBUS(PCIBus, qdev_get_parent_bus(qdev));
     devfn = pci_dev->devfn;
     pci_dev = do_pci_register_device(pci_dev, bus, base->name, devfn,
-                                     info->config_read, info->config_write);
+                                     info->config_read, info->config_write,
+                                     pci_get_config_initfn(info->header_type));
     assert(pci_dev);
     return info->init(pci_dev);
 }
diff --git a/hw/pci.h b/hw/pci.h
index e1d8564..15deb03 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -110,6 +110,14 @@ static inline int pci_bar_is_64bit(const PCIIORegion *r)
 #define  PCI_COMMAND_IO		0x1	/* Enable response in I/O space */
 #define  PCI_COMMAND_MEMORY	0x2	/* Enable response in Memory space */
 #define  PCI_COMMAND_MASTER	0x4	/* Enable bus master */
+#define  PCI_COMMAND_SPECIAL	0x8	/* Enable response to special cycles */
+#define  PCI_COMMAND_INVALIDATE 0x10	/* Use memory write and invalidate */
+#define  PCI_COMMAND_VGA_PALETTE 0x20	/* Enable palette snooping */
+#define  PCI_COMMAND_PARITY	0x40	/* Enable parity checking */
+#define  PCI_COMMAND_WAIT	0x80	/* Enable address/data stepping */
+#define  PCI_COMMAND_SERR	0x100	/* Enable SERR */
+#define  PCI_COMMAND_FAST_BACK	0x200	/* Enable back-to-back writes */
+#define  PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */
 #define PCI_STATUS              0x06    /* 16 bits */
 #define PCI_REVISION_ID         0x08    /* 8 bits  */
 #define PCI_CLASS_PROG		0x09	/* Reg. Level Programming Interface */
@@ -121,15 +129,30 @@ static inline int pci_bar_is_64bit(const PCIIORegion *r)
 #define  PCI_HEADER_TYPE_BRIDGE		1
 #define  PCI_HEADER_TYPE_CARDBUS	2
 #define  PCI_HEADER_TYPE_MULTI_FUNCTION 0x80
+#define PCI_BIST		0x0f	/* 8 bits */
+#define  PCI_BIST_CODE_MASK	0x0f	/* Return result */
+#define  PCI_BIST_START		0x40	/* 1 to start BIST, 2 secs or less */
+#define  PCI_BIST_CAPABLE	0x80	/* 1 if BIST capable */
 #define PCI_BASE_ADDRESS_0      0x10    /* 32 bits */
 #define PCI_BASE_ADDRESS_1      0x14    /* 32 bits [htype 0,1 only] */
 #define PCI_BASE_ADDRESS_2      0x18    /* 32 bits [htype 0 only] */
 #define PCI_BASE_ADDRESS_3      0x1c    /* 32 bits */
 #define PCI_BASE_ADDRESS_4      0x20    /* 32 bits */
 #define PCI_BASE_ADDRESS_5      0x24    /* 32 bits */
+#define  PCI_BASE_ADDRESS_SPACE		0x01	/* 0 = memory, 1 = I/O */
+#define  PCI_BASE_ADDRESS_SPACE_IO	0x01
+#define  PCI_BASE_ADDRESS_SPACE_MEMORY	0x00
+#define  PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06
+#define  PCI_BASE_ADDRESS_MEM_TYPE_32	0x00	/* 32 bit address */
+#define  PCI_BASE_ADDRESS_MEM_TYPE_1M	0x02	/* Below 1M [obsolete] */
+#define  PCI_BASE_ADDRESS_MEM_TYPE_64	0x04	/* 64 bit address */
+#define  PCI_BASE_ADDRESS_MEM_PREFETCH	0x08	/* prefetchable? */
+#define  PCI_BASE_ADDRESS_MEM_MASK	(~0x0fUL)
+#define  PCI_BASE_ADDRESS_IO_MASK	(~0x03UL)
 #define PCI_PRIMARY_BUS		0x18	/* Primary bus number */
 #define PCI_SECONDARY_BUS	0x19	/* Secondary bus number */
 #define PCI_SEC_STATUS		0x1e	/* Secondary status register, only bit 14 used */
+#define PCI_CARDBUS_CIS         0x28
 #define PCI_SUBSYSTEM_VENDOR_ID 0x2c    /* 16 bits */
 #define PCI_SUBSYSTEM_ID        0x2e    /* 16 bits */
 #define PCI_CAPABILITY_LIST	0x34	/* Offset of first capability list entry */
@@ -171,9 +194,45 @@ static inline int pci_bar_is_64bit(const PCIIORegion *r)
 #define PCI_COMMAND_RESERVED_MASK_HI (PCI_COMMAND_RESERVED >> 8)
 
 /* Header type 1 (PCI-to-PCI bridges) */
-#define PCI_ROM_ADDRESS1        0x38    /* Same as PCI_ROM_ADDRESS, but for htype 1 */
 #define PCI_SUBORDINATE_BUS     0x1a    /* Highest bus number behind the bridge */
+#define PCI_SEC_LATENCY_TIMER   0x1b    /* Latency timer for secondary interface */
+#define PCI_IO_BASE             0x1c    /* I/O range behind the bridge */
+#define PCI_IO_LIMIT            0x1d
+#define  PCI_IO_RANGE_TYPE_MASK 0x0fUL  /* I/O bridging type */
+#define  PCI_IO_RANGE_TYPE_16   0x00
+#define  PCI_IO_RANGE_TYPE_32   0x01
+#define  PCI_IO_RANGE_MASK      (~0x0fUL)
+#define PCI_MEMORY_BASE         0x20    /* Memory range behind */
+#define PCI_MEMORY_LIMIT        0x22
+#define  PCI_MEMORY_RANGE_TYPE_MASK 0x0fUL
+#define  PCI_MEMORY_RANGE_MASK  (~0x0fUL)
+#define PCI_PREF_MEMORY_BASE    0x24    /* Prefetchable memory range behind */
+#define PCI_PREF_MEMORY_LIMIT   0x26
+#define  PCI_PREF_RANGE_TYPE_MASK 0x0fUL
+#define  PCI_PREF_RANGE_TYPE_32 0x00
+#define  PCI_PREF_RANGE_TYPE_64 0x01
+#define  PCI_PREF_RANGE_MASK    (~0x0fUL)
+#define PCI_PREF_BASE_UPPER32   0x28    /* Upper half of prefetchable memory range */
+#define PCI_PREF_LIMIT_UPPER32  0x2c
+#define PCI_IO_BASE_UPPER16     0x30    /* Upper half of I/O addresses */
+#define PCI_IO_LIMIT_UPPER16    0x32
+/* 0x34 same as for htype 0 */
+/* 0x35-0x3b is reserved */
+#define PCI_ROM_ADDRESS1        0x38    /* Same as PCI_ROM_ADDRESS, but for htype 1 */
+/* 0x3c-0x3d are same as for htype 0 */
+#define PCI_BRIDGE_CONTROL      0x3e
+#define  PCI_BRIDGE_CTL_PARITY  0x01    /* Enable parity detection on secondary interface */
+#define  PCI_BRIDGE_CTL_SERR    0x02    /* The same for SERR forwarding */
+#define  PCI_BRIDGE_CTL_ISA     0x04    /* Enable ISA mode */
+#define  PCI_BRIDGE_CTL_VGA     0x08    /* Forward VGA addresses */
+#define  PCI_BRIDGE_CTL_MASTER_ABORT    0x20  /* Report master aborts */
+#define  PCI_BRIDGE_CTL_BUS_RESET       0x40    /* Secondary bus reset */
+#define  PCI_BRIDGE_CTL_FAST_BACK       0x80    /* Fast Back2Back enabled on secondary interface */
 
+/* Bits in the PCI Command Register (PCI 2.3 spec) */
+#define PCI_COMMAND_RESERVED_BRIDGE     0xf880
+
+#define PCI_COMMAND_RESERVED_MASK_HI_BRIDGE (PCI_COMMAND_RESERVED >> 8)
 
 /* Size of the standard PCI config header */
 #define PCI_CONFIG_HEADER_SIZE 0x40
@@ -460,6 +519,9 @@ typedef struct {
     PCIConfigReadFunc *config_read;
     PCIConfigWriteFunc *config_write;
 
+    /* pci config header type */
+    uint8_t header_type;
+
     /* pcie stuff */
     int pcie;
 } PCIDeviceInfo;
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 45/61] pci/monitor: print out bridge's filtering values and so on.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (43 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 44/61] pci: initialize wmask according to pci header type Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 46/61] pci/bridge: implement intel 82801ba bridge Isaku Yamahata
                   ` (19 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

make pci_info_device() print out bridge's filtering value like
io base/limit, subbus and subordinate bus.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |   43 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 43 insertions(+), 0 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 94fe87f..7aed737 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1150,7 +1150,50 @@ static void pci_info_device(PCIDevice *d)
                        d->config[PCI_INTERRUPT_LINE]);
     }
     if (class == 0x0604) {
+        int shift;
+        uint64_t base;
+        uint64_t limit;
         monitor_printf(mon, "      BUS %d.\n", d->config[0x19]);
+        monitor_printf(mon, "      SECONDARY BUS %d.\n",
+                       d->config[PCI_SECONDARY_BUS]);
+        monitor_printf(mon, "      SUBORDINATE BUS %d.\n",
+                       d->config[PCI_SUBORDINATE_BUS]);
+
+        if (d->config[PCI_IO_BASE] & PCI_IO_RANGE_TYPE_32) {
+            shift = 16;
+        } else {
+            shift = 8;
+        }
+        base = ((uint32_t)d->config[PCI_IO_BASE] & ~PCI_IO_RANGE_TYPE_MASK)
+            << shift;
+        base |= (uint32_t)pci_config_get_word(d, PCI_IO_BASE_UPPER16) << 16;
+        limit = ((uint32_t)d->config[PCI_IO_LIMIT] & ~PCI_IO_RANGE_TYPE_MASK)
+            << shift;
+        limit |= (uint32_t)pci_config_get_word(d, PCI_IO_LIMIT_UPPER16) << 16;
+        limit |= 0xfff;
+        monitor_printf(mon, "      IO range [0x%04"PRIx64", 0x%04"PRIx64"]\n",
+                       base, limit);
+
+        shift = 16;
+        base = ((uint32_t)pci_config_get_word(d, PCI_MEMORY_BASE) &
+                PCI_MEMORY_RANGE_MASK) << shift;
+        limit = ((uint32_t)pci_config_get_word(d, PCI_MEMORY_LIMIT) &
+                 PCI_MEMORY_RANGE_MASK) << shift;
+        limit |= 0xfffff;
+        monitor_printf(mon,
+                       "      MEM range [0x%08"PRIx64", 0x%08"PRIx64"]\n",
+                       base, limit);
+        shift = 16;
+        base = ((uint64_t)pci_config_get_word(d, PCI_PREF_MEMORY_BASE) &
+                PCI_PREF_RANGE_MASK) << shift;
+        limit = ((uint64_t)pci_config_get_word(d, PCI_PREF_MEMORY_LIMIT) &
+                 PCI_PREF_RANGE_MASK) << shift;
+        base |= (uint64_t)pci_config_get_long(d, PCI_PREF_BASE_UPPER32) << 32;
+        limit |= (uint64_t)pci_config_get_long(d, PCI_PREF_LIMIT_UPPER32) << 32;
+        limit |= 0xfffff;
+        monitor_printf(mon,
+                       "      pref MEM range [0x%08"PRIx64", 0x%08"PRIx64"]\n",
+                       base, limit);
     }
     for(i = 0;i < PCI_NUM_REGIONS; i++) {
         r = &d->io_regions[i];
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 46/61] pci/bridge: implement intel 82801ba bridge.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (44 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 45/61] pci/monitor: print out bridge's filtering values and so on Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 47/61] pci.h: add more status constats Isaku Yamahata
                   ` (18 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

implement intel 82801ba bridge.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 Makefile.target |    2 +-
 hw/pci_bridge.c |   63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/pci_bridge.h |   38 +++++++++++++++++++++++++++++++++
 hw/pci_ids.h    |    3 ++
 4 files changed, 105 insertions(+), 1 deletions(-)
 create mode 100644 hw/pci_bridge.c
 create mode 100644 hw/pci_bridge.h

diff --git a/Makefile.target b/Makefile.target
index fba44b8..ab5c098 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -145,7 +145,7 @@ endif #CONFIG_BSD_USER
 ifdef CONFIG_SOFTMMU
 
 obj-y = vl.o monitor.o pci.o isa_mmio.o machine.o \
-        gdbstub.o gdbstub-xml.o
+        gdbstub.o gdbstub-xml.o pci_bridge.o
 # virtio has to be here due to weird dependency between PCI and virtio-net.
 # need to fix this properly
 obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-console.o virtio-pci.o
diff --git a/hw/pci_bridge.c b/hw/pci_bridge.c
new file mode 100644
index 0000000..161a23d
--- /dev/null
+++ b/hw/pci_bridge.c
@@ -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, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ */
+
+#include <stdlib.h>
+
+#include "qdev.h"
+#include "pci.h"
+#include "pci_bridge.h"
+
+static PCIDeviceInfo i82801ba11_info = {
+    .qdev.name = PCI_BRIDGE_INTEL_82801BA_11,
+    .qdev.size = sizeof(PCIDevice),
+
+    .config_write = pci_bridge_write_config,
+    .init = pci_bridge_initfn,
+
+    .header_type = PCI_HEADER_TYPE_BRIDGE,
+    .pcie = 1,
+};
+
+static void i82801ba11_register_device(void)
+{
+    pci_qdev_register(&i82801ba11_info);
+}
+
+device_init(i82801ba11_register_device);
+
+PCIBus *i82801ba11_init(PCIBus *bus, int devfn, int sec_bus, int sub_bus)
+{
+    return pci_bridge_create_simple(bus, devfn,
+                                    PCI_VENDOR_ID_INTEL,
+                                    PCI_DEVICE_ID_INTEL_82801BA_11,
+                                    sec_bus, sub_bus,
+                                    pci_swizzle_map_irq_fn,
+                                    PCI_BRIDGE_INTEL_82801BA_11,
+                                    PCI_BRIDGE_INTEL_82801BA_11);
+}
+
+/*
+ * Local variables:
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 8
+ *  indent-tab-mode: nil
+ * End:
+ */
diff --git a/hw/pci_bridge.h b/hw/pci_bridge.h
new file mode 100644
index 0000000..90eeaeb
--- /dev/null
+++ b/hw/pci_bridge.h
@@ -0,0 +1,38 @@
+/*
+ * 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, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ */
+
+#ifndef QEMU_PCI_BRIDGE_H
+#define QEMU_PCI_BRIDGE_H
+
+#include "pci.h"
+
+#define PCI_BRIDGE_INTEL_82801BA_11     "i82801ba11"
+
+PCIBus *i82801ba11_init(PCIBus *bus, int devfn, int sec_bus, int sub_bus);
+
+#endif  /* QEMU_PCI_BRIDGE_H */
+/*
+ * Local variables:
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 8
+ *  indent-tab-mode: nil
+ * End:
+ */
diff --git a/hw/pci_ids.h b/hw/pci_ids.h
index 3afe674..f7d0387 100644
--- a/hw/pci_ids.h
+++ b/hw/pci_ids.h
@@ -88,6 +88,7 @@
 #define PCI_VENDOR_ID_INTEL              0x8086
 #define PCI_DEVICE_ID_INTEL_82441        0x1237
 #define PCI_DEVICE_ID_INTEL_82801AA_5    0x2415
+#define PCI_DEVICE_ID_INTEL_82801BA_11   0x244e
 #define PCI_DEVICE_ID_INTEL_82371SB_0    0x7000
 #define PCI_DEVICE_ID_INTEL_82371SB_1    0x7010
 #define PCI_DEVICE_ID_INTEL_82371SB_2    0x7020
@@ -95,3 +96,5 @@
 #define PCI_DEVICE_ID_INTEL_82371AB      0x7111
 #define PCI_DEVICE_ID_INTEL_82371AB_2    0x7112
 #define PCI_DEVICE_ID_INTEL_82371AB_3    0x7113
+
+#define PCI_VENDOR_ID_INVALID            0xffff
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 47/61] pci.h: add more status constats.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (45 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 46/61] pci/bridge: implement intel 82801ba bridge Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 48/61] pci id: add subclass codes for serial device Isaku Yamahata
                   ` (17 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.h |   22 ++++++++++++++++------
 1 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/hw/pci.h b/hw/pci.h
index 15deb03..aed4a44 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -176,15 +176,25 @@ static inline int pci_bar_is_64bit(const PCIIORegion *r)
 /* Bits in the PCI Status Register (PCI 2.3 spec) */
 #define PCI_STATUS_RESERVED1	0x007
 #define PCI_STATUS_INT_STATUS	0x008
-#define PCI_STATUS_CAP_LIST	0x010
-#define PCI_STATUS_66MHZ	0x020
-#define PCI_STATUS_RESERVED2	0x040
-#define PCI_STATUS_FAST_BACK	0x080
+#define PCI_STATUS_CAP_LIST	0x010   /* Support Capability List */
+#define PCI_STATUS_66MHZ	0x020   /* Support 66 Mhz PCI 2.1 bus */
+#define PCI_STATUS_UDF		0x040	/* Support User Definable Features [obsolete] */
+#define PCI_STATUS_FAST_BACK	0x080   /* Accept fast-back to back */
+#define PCI_STATUS_PARITY	0x100	/* Detected parity error */
 #define PCI_STATUS_DEVSEL	0x600
+#define PCI_STATUS_DEVSEL_MASK	0x600	/* DEVSEL timing */
+#define PCI_STATUS_DEVSEL_FAST		0x000
+#define PCI_STATUS_DEVSEL_MEDIUM	0x200
+#define PCI_STATUS_DEVSEL_SLOW		0x400
+#define PCI_STATUS_SIG_TARGET_ABORT	0x800 /* Set on target abort */
+#define PCI_STATUS_REC_TARGET_ABORT	0x1000 /* Master ack of " */
+#define PCI_STATUS_REC_MASTER_ABORT	0x2000 /* Set on master abort */
+#define PCI_STATUS_SIG_SYSTEM_ERROR	0x4000 /* Set when we drive SERR */
+#define PCI_STATUS_DETECTED_PARITY	0x8000 /* Set on parity error */
 
 #define PCI_STATUS_RESERVED_MASK_LO (PCI_STATUS_RESERVED1 | \
-                PCI_STATUS_INT_STATUS | PCI_STATUS_CAPABILITIES | \
-                PCI_STATUS_66MHZ | PCI_STATUS_RESERVED2 | PCI_STATUS_FAST_BACK)
+                PCI_STATUS_INT_STATUS | PCI_STATUS_CAP_LIST | \
+                PCI_STATUS_66MHZ | PCI_STATUS_UDF | PCI_STATUS_FAST_BACK)
 
 #define PCI_STATUS_RESERVED_MASK_HI (PCI_STATUS_DEVSEL >> 8)
 
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 48/61] pci id: add subclass codes for serial device.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (46 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 47/61] pci.h: add more status constats Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 49/61] pci hot add: pass opaque argument to callback Isaku Yamahata
                   ` (16 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

subclass codes for serial device.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci_ids.h |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/hw/pci_ids.h b/hw/pci_ids.h
index f7d0387..7eef2cd 100644
--- a/hw/pci_ids.h
+++ b/hw/pci_ids.h
@@ -40,6 +40,18 @@
 #define PCI_CLASS_PROCESSOR_CO           0x0b40
 #define PCI_CLASS_PROCESSOR_POWERPC      0x0b20
 
+#define PCI_BASE_CLASS_SERIAL            0x0c
+#define PCI_CLASS_SERIAL_FIREWIRE        0x0c00
+#define PCI_CLASS_SERIAL_FIREWIRE_OHCI   0x0c0010
+#define PCI_CLASS_SERIAL_ACCESS          0x0c01
+#define PCI_CLASS_SERIAL_SSA             0x0c02
+#define PCI_CLASS_SERIAL_USB             0x0c03
+#define PCI_CLASS_SERIAL_USB_UHCI        0x0c0300
+#define PCI_CLASS_SERIAL_USB_OHCI        0x0c0310
+#define PCI_CLASS_SERIAL_USB_EHCI        0x0c0320
+#define PCI_CLASS_SERIAL_FIBER           0x0c04
+#define PCI_CLASS_SERIAL_SMBUS           0x0c05
+
 #define PCI_CLASS_OTHERS                 0xff
 
 /* Vendors and devices.  Sort key: vendor first, device next. */
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 49/61] pci hot add: pass opaque argument to callback.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (47 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 48/61] pci id: add subclass codes for serial device Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 50/61] pci hotadd, acpi_piix4: remove global variables Isaku Yamahata
                   ` (15 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

pass opaque argument to callback.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/acpi.c       |    8 ++++++--
 hw/acpi_piix4.c |    6 +++---
 sysemu.h        |    4 ++--
 3 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/hw/acpi.c b/hw/acpi.c
index 44056a1..4b1c5c8 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -22,15 +22,19 @@
 #include "acpi.h"
 
 static qemu_system_device_hot_add_t device_hot_add_callback;
-void qemu_system_device_hot_add_register(qemu_system_device_hot_add_t callback)
+static void *device_hot_add_arg;
+
+void qemu_system_device_hot_add_register(qemu_system_device_hot_add_t callback,
+void *opaque)
 {
     device_hot_add_callback = callback;
+    device_hot_add_arg = opaque;
 }
 
 void qemu_system_device_hot_add(int pcibus, int slot, int state)
 {
     if (device_hot_add_callback)
-        device_hot_add_callback(pcibus, slot, state);
+        device_hot_add_callback(pcibus, slot, state, device_hot_add_arg);
 }
 
 struct acpi_table_header
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 5f3ee9a..c11e1b9 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -526,7 +526,7 @@ static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
 #endif
 }
 
-static void piix4_device_hot_add(int bus, int slot, int state);
+static void piix4_device_hot_add(int bus, int slot, int state, void* opaque);
 
 void piix4_acpi_system_hot_add_init(void)
 {
@@ -539,7 +539,7 @@ void piix4_acpi_system_hot_add_init(void)
     register_ioport_write(PCI_EJ_BASE, 4, 4, pciej_write, NULL);
     register_ioport_read(PCI_EJ_BASE, 4, 4,  pciej_read, NULL);
 
-    qemu_system_device_hot_add_register(piix4_device_hot_add);
+    qemu_system_device_hot_add_register(piix4_device_hot_add, NULL);
 }
 
 static void enable_device(struct pci_status *p, struct gpe_regs *g, int slot)
@@ -554,7 +554,7 @@ static void disable_device(struct pci_status *p, struct gpe_regs *g, int slot)
     p->down |= (1 << slot);
 }
 
-static void piix4_device_hot_add(int bus, int slot, int state)
+static void piix4_device_hot_add(int bus, int slot, int state, void *opaque)
 {
     pci0_status.up = 0;
     pci0_status.down = 0;
diff --git a/sysemu.h b/sysemu.h
index 8bf90ee..1450c65 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -198,8 +198,8 @@ extern QemuOpts *drive_add(const char *file, const char *fmt, ...);
 extern DriveInfo *drive_init(QemuOpts *arg, void *machine, int *fatal_error);
 
 /* acpi */
-typedef void (*qemu_system_device_hot_add_t)(int pcibus, int slot, int state);
-void qemu_system_device_hot_add_register(qemu_system_device_hot_add_t callback);
+typedef void (*qemu_system_device_hot_add_t)(int pcibus, int slot, int state, void *opaque);
+void qemu_system_device_hot_add_register(qemu_system_device_hot_add_t callback, void *opaque);
 void qemu_system_device_hot_add(int pcibus, int slot, int state);
 
 /* device-hotplug */
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 50/61] pci hotadd, acpi_piix4: remove global variables.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (48 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 49/61] pci hot add: pass opaque argument to callback Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 51/61] vmstate: add a macro for pointer to struct, VMSTATE_STRUCT_POINTER Isaku Yamahata
                   ` (14 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

remove global variables.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/acpi_piix4.c |   53 +++++++++++++++++++++++++++++++++--------------------
 hw/pc.h         |    1 -
 hw/pc_piix.c    |    2 --
 3 files changed, 33 insertions(+), 23 deletions(-)

diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index c11e1b9..38c6a53 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -47,11 +47,11 @@ typedef struct PIIX4PMState {
     qemu_irq irq;
 } PIIX4PMState;
 
+static void piix4_acpi_system_hot_add_init(PIIX4PMState *s);
+
 #define ACPI_ENABLE 0xf1
 #define ACPI_DISABLE 0xf0
 
-static PIIX4PMState *pm_state;
-
 static uint32_t get_pmtmr(PIIX4PMState *s)
 {
     uint32_t d;
@@ -328,7 +328,8 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
     s = (PIIX4PMState *)pci_register_device(bus,
                                          "PM", sizeof(PIIX4PMState),
                                          devfn, NULL, pm_write_config);
-    pm_state = s;
+    piix4_acpi_system_hot_add_init(s);
+
     pci_conf = s->dev.config;
     pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
     pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371AB_3);
@@ -393,9 +394,6 @@ struct pci_status {
     uint32_t down;
 };
 
-static struct gpe_regs gpe;
-static struct pci_status pci0_status;
-
 static uint32_t gpe_read_val(uint16_t val, uint32_t addr)
 {
     if (addr & 1)
@@ -526,20 +524,33 @@ static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
 #endif
 }
 
-static void piix4_device_hot_add(int bus, int slot, int state, void* opaque);
+static void piix4_device_hot_add(int bus, int slot, int state, void *opaque);
 
-void piix4_acpi_system_hot_add_init(void)
+struct piix4_hot_add {
+    struct gpe_regs *gpe;
+    struct pci_status *pci0_status;
+    PIIX4PMState *pm_state;
+};
+
+static void piix4_acpi_system_hot_add_init(PIIX4PMState *s)
 {
-    register_ioport_write(GPE_BASE, 4, 1, gpe_writeb, &gpe);
-    register_ioport_read(GPE_BASE, 4, 1,  gpe_readb, &gpe);
+    struct gpe_regs *gpe = qemu_mallocz(sizeof(*gpe));
+    struct pci_status *pci0_status = qemu_mallocz(sizeof(*pci0_status));
+    struct piix4_hot_add *hot_add_arg = qemu_malloc(sizeof(*hot_add_arg));
+    hot_add_arg->gpe = gpe;
+    hot_add_arg->pci0_status = pci0_status;
+    hot_add_arg->pm_state = s;
 
-    register_ioport_write(PCI_BASE, 8, 4, pcihotplug_write, &pci0_status);
-    register_ioport_read(PCI_BASE, 8, 4,  pcihotplug_read, &pci0_status);
+    register_ioport_write(GPE_BASE, 4, 1, gpe_writeb, gpe);
+    register_ioport_read(GPE_BASE, 4, 1,  gpe_readb, gpe);
+
+    register_ioport_write(PCI_BASE, 8, 4, pcihotplug_write, pci0_status);
+    register_ioport_read(PCI_BASE, 8, 4,  pcihotplug_read, pci0_status);
 
     register_ioport_write(PCI_EJ_BASE, 4, 4, pciej_write, NULL);
     register_ioport_read(PCI_EJ_BASE, 4, 4,  pciej_read, NULL);
 
-    qemu_system_device_hot_add_register(piix4_device_hot_add, NULL);
+    qemu_system_device_hot_add_register(piix4_device_hot_add, hot_add_arg);
 }
 
 static void enable_device(struct pci_status *p, struct gpe_regs *g, int slot)
@@ -556,14 +567,16 @@ static void disable_device(struct pci_status *p, struct gpe_regs *g, int slot)
 
 static void piix4_device_hot_add(int bus, int slot, int state, void *opaque)
 {
-    pci0_status.up = 0;
-    pci0_status.down = 0;
+    struct piix4_hot_add *hot_add_arg = opaque;
+
+    hot_add_arg->pci0_status->up = 0;
+    hot_add_arg->pci0_status->down = 0;
     if (state)
-        enable_device(&pci0_status, &gpe, slot);
+        enable_device(hot_add_arg->pci0_status, hot_add_arg->gpe, slot);
     else
-        disable_device(&pci0_status, &gpe, slot);
-    if (gpe.en & 2) {
-        qemu_set_irq(pm_state->irq, 1);
-        qemu_set_irq(pm_state->irq, 0);
+        disable_device(hot_add_arg->pci0_status, hot_add_arg->gpe, slot);
+    if (hot_add_arg->gpe->en & 2) {
+        qemu_set_irq(hot_add_arg->pm_state->irq, 1);
+        qemu_set_irq(hot_add_arg->pm_state->irq, 0);
     }
 }
diff --git a/hw/pc.h b/hw/pc.h
index dcb62a4..cf34db6 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -148,7 +148,6 @@ int acpi_table_add(const char *table_desc);
 i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
                        qemu_irq sci_irq);
 void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr);
-void piix4_acpi_system_hot_add_init(void);
 
 /* hpet.c */
 extern int no_hpet;
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 4c8bb27..55b53d0 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -108,8 +108,6 @@ static void pc_init1(ram_addr_t ram_size,
             pci_nic_init(nd, "e1000", NULL);
     }
 
-    piix4_acpi_system_hot_add_init();
-
     if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
         fprintf(stderr, "qemu: too many IDE bus\n");
         exit(1);
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 51/61] vmstate: add a macro for pointer to struct, VMSTATE_STRUCT_POINTER.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (49 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 50/61] pci hotadd, acpi_piix4: remove global variables Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 52/61] pci: add a hook to replace default pci bus instead of 0 bus Isaku Yamahata
                   ` (13 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

introduce VMSTATE_STRUCT_POINTER which is for a pointer to a struct.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/hw.h |   10 ++++++++++
 1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/hw/hw.h b/hw/hw.h
index 478b0b2..19e9199 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -387,6 +387,16 @@ extern const VMStateInfo vmstate_info_buffer;
             + type_check(_type,typeof_field(_state, _field))         \
 }
 
+#define VMSTATE_STRUCT_POINTER(_field, _state, _version, _vmsd, _type) { \
+    .name       = (stringify(_field)),                               \
+    .version_id = (_version),                                        \
+    .vmsd       = &(_vmsd),                                          \
+    .size       = sizeof(_type),                                     \
+    .flags      = VMS_STRUCT|VMS_POINTER,                            \
+    .offset     = offsetof(_state, _field)                           \
+            + type_check(_type,typeof_field(_state, _field))         \
+}
+
 #define VMSTATE_STRUCT_ARRAY(_field, _state, _num, _version, _vmsd, _type) { \
     .name       = (stringify(_field)),                               \
     .num        = (_num),                                            \
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 52/61] pci: add a hook to replace default pci bus instead of 0 bus.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (50 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 51/61] vmstate: add a macro for pointer to struct, VMSTATE_STRUCT_POINTER Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 53/61] pc q35 based chipset emulator Isaku Yamahata
                   ` (12 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

add a register function to replace default pci bus of 0.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |   10 ++++++++++
 hw/pci.h |    1 +
 2 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 7aed737..05cd2cb 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -343,6 +343,14 @@ int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
     return 0;
 }
 
+static PCIBus *pci_default_bus;
+
+void pci_set_default_bus(PCIBus *bus)
+{
+    assert(pci_default_bus == NULL);
+    pci_default_bus = bus;
+}
+
 static PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr)
 {
     int dom, bus;
@@ -350,6 +358,8 @@ static PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr)
 
     if (!devaddr) {
         *devfnp = -1;
+        if (pci_default_bus)
+            return pci_default_bus;
         return pci_find_bus(0);
     }
 
diff --git a/hw/pci.h b/hw/pci.h
index aed4a44..27a5d33 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -352,6 +352,7 @@ void pci_default_write_config(PCIDevice *d,
                               uint32_t address, uint32_t val, int len);
 void pci_device_save(PCIDevice *s, QEMUFile *f);
 int pci_device_load(PCIDevice *s, QEMUFile *f);
+void pci_set_default_bus(PCIBus *bus);
 
 typedef void (*pci_set_irq_fn)(void *opaque, int irq_num, int level);
 typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num);
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 53/61] pc q35 based chipset emulator
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (51 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 52/61] pci: add a hook to replace default pci bus instead of 0 bus Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-10-05 10:30   ` [Qemu-devel] " Michael S. Tsirkin
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 54/61] pci: add opaque argument to pci_map_irq_fn() Isaku Yamahata
                   ` (11 subsequent siblings)
  64 siblings, 1 reply; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

pc q35 based chipset emulator

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 Makefile.target |    1 +
 hw/acpi_ich9.c  |  565 ++++++++++++++++++++++++++++++++++++++++++
 hw/acpi_ich9.h  |   57 +++++
 hw/pc_q35.c     |  220 +++++++++++++++++
 hw/pci_ids.h    |   13 +
 hw/q35.c        |  731 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/q35.h        |  228 +++++++++++++++++
 hw/q35_smbus.c  |  150 ++++++++++++
 8 files changed, 1965 insertions(+), 0 deletions(-)
 create mode 100644 hw/acpi_ich9.c
 create mode 100644 hw/acpi_ich9.h
 create mode 100644 hw/pc_q35.c
 create mode 100644 hw/q35.c
 create mode 100644 hw/q35.h
 create mode 100644 hw/q35_smbus.c

diff --git a/Makefile.target b/Makefile.target
index ab5c098..9990942 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -188,6 +188,7 @@ obj-i386-y += usb-uhci.o vmmouse.o vmport.o vmware_vga.o hpet.o
 obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
 obj-i386-y += ne2000-isa.o
 obj-i386-y += pc_smbus.o pc_apm.o acpi_piix4.o pc_piix.o
+obj-i386-y += pc_q35.o q35.o q35_smbus.o acpi_ich9.o
 
 # shared objects
 obj-ppc-y = ppc.o ide/core.o ide/qdev.o ide/isa.o ide/pci.o ide/macio.o
diff --git a/hw/acpi_ich9.c b/hw/acpi_ich9.c
new file mode 100644
index 0000000..82e4d5c
--- /dev/null
+++ b/hw/acpi_ich9.c
@@ -0,0 +1,565 @@
+/*
+ * ACPI implementation
+ *
+ * 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 Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+/*
+ *  Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ *                     VA Linux Systems Japan K.K.
+ *
+ *  This is based on acpi.c.
+ */
+#include "hw.h"
+#include "pc.h"
+#include "pci.h"
+#include "qemu-timer.h"
+#include "sysemu.h"
+#include "acpi.h"
+
+#include "q35.h"
+
+//#define DEBUG
+
+#ifdef DEBUG
+#define ICH9_DEBUG(fmt, ...)    do { printf("%s "fmt, __func__, ## __VA_ARGS__); } while (0)
+#else
+#define ICH9_DEBUG(fmt, ...)    do { } while (0)
+#endif
+
+/* XXX where does the constant, ACPI_DBG_IO_ADDR, come from */
+/* 0xb044 is used on ich9. 0xb080 or something. */
+//#define ACPI_DBG_IO_ADDR  0xb044
+// 0xb044 is already used.
+#define ACPI_DBG_IO_ADDR  0xb080
+static void ich9_acpi_dbg_writel(void *opaqe, uint32_t addr, uint32_t val)
+{
+    ICH9_DEBUG("0x%08x\n", val);
+}
+
+void ich9_acpi_dbg_init(void);
+void ich9_acpi_dbg_init(void)
+{
+    register_ioport_write(ACPI_DBG_IO_ADDR, 4, 4, ich9_acpi_dbg_writel, NULL);
+}
+
+
+static void pm_ioport_write_fallback(void *opaque, uint32_t addr, int len,
+                                     uint32_t val);
+static uint32_t pm_ioport_read_fallback(void *opaque, uint32_t addr, int len);
+static void gpe_ioport_writeb(struct ich9_lpc_pm_regs *pm,
+                              uint32_t addr, uint32_t val);
+static uint32_t gpe_ioport_readb(struct ich9_lpc_pm_regs *pm,
+                                 uint32_t addr);
+
+static uint32_t get_pmtmr(struct ich9_lpc_pm_regs *pm)
+{
+    uint32_t d;
+    d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY,
+                 get_ticks_per_sec());
+    return d & 0xffffff;
+}
+
+static int get_pm1_sts(struct ich9_lpc_pm_regs *pm)
+{
+    int64_t d;
+    d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY,
+                 get_ticks_per_sec());
+    if (d >= pm->tmr_overflow_time)
+        pm->pm1_sts |= ACPI_BITMASK_TIMER_STATUS;
+    return pm->pm1_sts;
+}
+
+static void pm_update_sci(struct ich9_lpc_pm_regs *pm)
+{
+    int sci_level, pm1_sts;
+    int64_t expire_time;
+
+    pm1_sts = get_pm1_sts(pm);
+    sci_level = (((pm1_sts & pm->pm1_en) &
+                  (ACPI_BITMASK_RT_CLOCK_ENABLE |
+                   ACPI_BITMASK_POWER_BUTTON_ENABLE |
+                   ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
+                   ACPI_BITMASK_TIMER_ENABLE)) != 0);
+    qemu_set_irq(pm->irq, sci_level);
+    /* schedule a timer interruption if needed */
+    if ((pm->pm1_en & ACPI_BITMASK_TIMER_ENABLE) &&
+        !(pm1_sts & ACPI_BITMASK_TIMER_STATUS)) {
+        expire_time = muldiv64(pm->tmr_overflow_time, get_ticks_per_sec(),
+                               PM_TIMER_FREQUENCY);
+        qemu_mod_timer(pm->tmr_timer, expire_time);
+    } else {
+        qemu_del_timer(pm->tmr_timer);
+    }
+}
+
+static void pm_tmr_timer(void *opaque)
+{
+    struct ich9_lpc_pm_regs *pm = opaque;
+    pm_update_sci(pm);
+}
+
+static void pm_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+    struct ich9_lpc_pm_regs *pm = opaque;
+
+    switch (addr & ICH9_PMIO_MASK) {
+    case ICH9_PMIO_GPE0_STS ... (ICH9_PMIO_GPE0_STS + 7):
+    case ICH9_PMIO_GPE0_EN ... (ICH9_PMIO_GPE0_EN + 7):
+        gpe_ioport_writeb(pm, addr, val);
+        break;
+    default:
+        break;
+    }
+
+    ICH9_DEBUG("port=0x%04x val=0x%04x\n", addr, val);
+}
+
+static uint32_t pm_ioport_readb(void *opaque, uint32_t addr)
+{
+    struct ich9_lpc_pm_regs *pm = opaque;
+    uint32_t val = 0;
+
+    switch(addr & ICH9_PMIO_MASK) {
+    case ICH9_PMIO_GPE0_STS ... (ICH9_PMIO_GPE0_STS + 7):
+    case ICH9_PMIO_GPE0_EN ... (ICH9_PMIO_GPE0_EN + 7):
+        val = gpe_ioport_readb(pm, addr);
+        break;
+    default:
+        val = 0;
+        break;
+    }
+    ICH9_DEBUG("port=0x%04x val=0x%04x\n", addr, val);
+    return val;
+}
+
+static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
+{
+    struct ich9_lpc_pm_regs *pm = opaque;
+
+    switch(addr & ICH9_PMIO_MASK) {
+    case ICH9_PMIO_PM1_STS:
+        {
+            int64_t d;
+            int pm1_sts;
+            pm1_sts = get_pm1_sts(pm);
+            if (pm1_sts & val & ACPI_BITMASK_TIMER_STATUS) {
+                /* if TMRSTS is reset, then compute the new overflow time */
+                d = muldiv64(qemu_get_clock(vm_clock), PM_TIMER_FREQUENCY,
+                             get_ticks_per_sec());
+                pm->tmr_overflow_time = (d + 0x800000LL) & ~0x7fffffLL;
+            }
+            pm->pm1_sts &= ~val;
+            pm_update_sci(pm);
+        }
+        break;
+    case ICH9_PMIO_PM1_EN:
+        pm->pm1_en = val;
+        pm_update_sci(pm);
+        break;
+    case ICH9_PMIO_PM1_CNT:
+        {
+            int sus_typ;
+            pm->pm1_cnt = val & ~(ACPI_BITMASK_SLEEP_ENABLE);
+            if (val & ACPI_BITMASK_SLEEP_ENABLE) {
+                /* change suspend type */
+                sus_typ = (val >> 10) & 7;
+                switch(sus_typ) {
+                case 0: /* soft power off */
+                    qemu_system_shutdown_request();
+                    break;
+                case 1:
+                    /* ACPI_BITMASK_WAKE_STATUS should be set on resume.
+                       Pretend that resume was caused by power button */
+                    pm->pm1_sts |= (ACPI_BITMASK_WAKE_STATUS |
+                                 ACPI_BITMASK_POWER_BUTTON_STATUS);
+                    qemu_system_reset_request();
+#if defined(TARGET_I386)
+                    cmos_set_s3_resume();
+#endif
+                default:
+                    break;
+                }
+            }
+        }
+        break;
+    default:
+        pm_ioport_write_fallback(opaque, addr, 2, val);
+        break;
+    }
+    ICH9_DEBUG("port=0x%04x val=0x%04x\n", addr, val);
+}
+
+static uint32_t pm_ioport_readw(void *opaque, uint32_t addr)
+{
+    struct ich9_lpc_pm_regs *pm = opaque;
+    uint32_t val;
+
+    switch(addr & ICH9_PMIO_MASK) {
+    case ICH9_PMIO_PM1_STS:
+        val = get_pm1_sts(pm);
+        break;
+    case ICH9_PMIO_PM1_EN:
+        val = pm->pm1_en;
+        break;
+    case ICH9_PMIO_PM1_CNT:
+        val = pm->pm1_cnt;
+        break;
+    default:
+        val = pm_ioport_read_fallback(opaque, addr, 2);
+        break;
+    }
+    ICH9_DEBUG("port=0x%04x val=0x%04x\n", addr, val);
+    return val;
+}
+
+static void pm_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
+{
+    struct ich9_lpc_pm_regs *pm = opaque;
+
+    switch(addr & ICH9_PMIO_MASK) {
+    case ICH9_PMIO_SMI_EN:
+        pm->smi_en = val;
+        break;
+    default:
+        pm_ioport_write_fallback(opaque, addr, 4, val);
+        break;
+    }
+    ICH9_DEBUG("port=0x%04x val=0x%08x\n", addr, val);
+}
+
+static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
+{
+    struct ich9_lpc_pm_regs *pm = opaque;
+    uint32_t val;
+
+    switch(addr & ICH9_PMIO_MASK) {
+    case ICH9_PMIO_PM1_TMR:
+        val = get_pmtmr(pm);
+        break;
+    case ICH9_PMIO_SMI_EN:
+        val = pm->smi_en;
+        break;
+
+    default:
+        val = pm_ioport_read_fallback(opaque, addr, 4);
+        break;
+    }
+    ICH9_DEBUG("port=0x%04x val=0x%08x\n", addr, val);
+    return val;
+}
+
+static void pm_ioport_write_fallback(void *opaque, uint32_t addr, int len,
+                                     uint32_t val)
+{
+    int subsize = (len == 4)? 2: 1;
+    IOPortWriteFunc *ioport_write =
+        (subsize == 2)? pm_ioport_writew: pm_ioport_writeb;
+
+    int i;
+
+    for (i = 0; i < len; i += subsize) {
+        ioport_write(opaque, addr, val);
+        val >>= 8 * subsize;
+    }
+}
+
+static uint32_t pm_ioport_read_fallback(void *opaque, uint32_t addr, int len)
+{
+    int subsize = (len == 4)? 2: 1;
+    IOPortReadFunc *ioport_read =
+        (subsize == 2)? pm_ioport_readw: pm_ioport_readb;
+
+    uint32_t val;
+    int i;
+
+    val = 0;
+    for (i = 0; i < len; i += subsize) {
+        val <<= 8 * subsize;
+        val |= ioport_read(opaque, addr);
+    }
+
+    return val;
+}
+
+void ich9_pm_iospace_update(struct ich9_lpc_pm_regs *pm, uint32_t pm_io_base)
+{
+    ICH9_DEBUG("to 0x%x\n", pm_io_base);
+
+    assert((pm_io_base & ICH9_PMIO_MASK) == 0);
+
+    if (pm->pm_io_base != 0)
+        isa_unassign_ioport(pm->pm_io_base, ICH9_PMIO_SIZE);
+
+    /* XXX: tmp hack */
+    if (pm_io_base == 0)
+        return;
+
+    register_ioport_write(pm_io_base, ICH9_PMIO_SIZE, 1, pm_ioport_writeb, pm);
+    register_ioport_read(pm_io_base, ICH9_PMIO_SIZE, 1, pm_ioport_readb, pm);
+    register_ioport_write(pm_io_base, ICH9_PMIO_SIZE, 2, pm_ioport_writew, pm);
+    register_ioport_read(pm_io_base, ICH9_PMIO_SIZE, 2, pm_ioport_readw, pm);
+    register_ioport_write(pm_io_base, ICH9_PMIO_SIZE, 4, pm_ioport_writel, pm);
+    register_ioport_read(pm_io_base, ICH9_PMIO_SIZE, 4, pm_ioport_readl, pm);
+
+    pm->pm_io_base = pm_io_base;
+}
+
+#define PCI_BUS_MAX     256
+struct ich9_pci_status {
+    uint32_t up[PCI_BUS_MAX];
+    uint32_t down[PCI_BUS_MAX];
+    uint8_t bus;
+};
+
+const VMStateDescription vmstate_ich9_pci_status = {
+    .name = "ich9_pci_status",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(up, struct ich9_pci_status, PCI_BUS_MAX),
+        VMSTATE_UINT32_ARRAY(down, struct ich9_pci_status, PCI_BUS_MAX),
+        VMSTATE_UINT8(bus, struct ich9_pci_status),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+const VMStateDescription vmstate_ich9_pm = {
+    .name = "ich9_pm",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT16(pm1_sts, struct ich9_lpc_pm_regs),
+        VMSTATE_UINT16(pm1_en, struct ich9_lpc_pm_regs),
+        VMSTATE_UINT16(pm1_cnt, struct ich9_lpc_pm_regs),
+        VMSTATE_TIMER(tmr_timer, struct ich9_lpc_pm_regs),
+        VMSTATE_INT64(tmr_overflow_time, struct ich9_lpc_pm_regs),
+        VMSTATE_UINT64(gpe0_sts, struct ich9_lpc_pm_regs),
+        VMSTATE_UINT64(gpe0_en, struct ich9_lpc_pm_regs),
+        VMSTATE_UINT32(smi_en, struct ich9_lpc_pm_regs),
+        VMSTATE_UINT32(smi_sts, struct ich9_lpc_pm_regs),
+        VMSTATE_STRUCT_POINTER(pci_status, struct ich9_lpc_pm_regs, 0,
+                               vmstate_ich9_pci_status,
+                               struct ich9_pci_status*),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void pm_reset(void *opaque)
+{
+    //struct ich9_lpc_pm_regs *pm = opaque;
+    /* XXX:TODO */
+}
+
+static void pm_powerdown(void *opaque, int irq, int power_failing)
+{
+#if defined(TARGET_I386)
+    struct ich9_lpc_pm_regs *pm = (struct ich9_lpc_pm_regs*) opaque;
+
+    if (!pm) {
+        qemu_system_shutdown_request();
+    } else if (pm->pm1_en & ACPI_BITMASK_POWER_BUTTON_ENABLE) {
+        pm->pm1_sts |= ACPI_BITMASK_POWER_BUTTON_STATUS;
+        pm_update_sci(pm);
+    }
+#endif
+}
+
+void ich9_pm_init(struct ich9_lpc_pm_regs *pm, qemu_irq sci_irq)
+{
+    pm->tmr_timer = qemu_new_timer(vm_clock, pm_tmr_timer, pm);
+
+    pm->irq = sci_irq;
+    qemu_register_reset(pm_reset, pm);
+    qemu_system_powerdown = *qemu_allocate_irqs(pm_powerdown, pm, 1);
+}
+
+/* GPE */
+#define GPE_ADDR_MASK   0xff
+
+static uint8_t *gpe_ioport_get_ptr(struct ich9_lpc_pm_regs *pm, uint32_t addr)
+{
+    uint8_t *cur = NULL;
+
+    addr &= GPE_ADDR_MASK;
+    switch (addr) {
+    case ICH9_PMIO_GPE0_STS ... (ICH9_PMIO_GPE0_STS + 7):
+        cur = (uint8_t*)&pm->gpe0_sts;
+        cur += addr - ICH9_PMIO_GPE0_STS;
+        break;
+    case ICH9_PMIO_GPE0_EN ... (ICH9_PMIO_GPE0_EN + 7):
+        cur = (uint8_t*)&pm->gpe0_en;
+        cur += addr - ICH9_PMIO_GPE0_EN;
+        break;
+    default:
+        abort();
+        break;
+    }
+    return cur;
+}
+
+static void gpe_ioport_writeb(struct ich9_lpc_pm_regs *pm,
+                              uint32_t addr, uint32_t val)
+{
+    uint8_t *cur = gpe_ioport_get_ptr(pm, addr);
+
+    switch (addr & GPE_ADDR_MASK) {
+    case ICH9_PMIO_GPE0_STS ... (ICH9_PMIO_GPE0_STS + 7):
+        *cur = (*cur) & ~val;
+        break;
+    case ICH9_PMIO_GPE0_EN ... (ICH9_PMIO_GPE0_EN + 7):
+        *cur = val;
+        break;
+    default:
+        abort();
+        break;
+    }
+    ICH9_DEBUG("%x <== %d\n", addr, val);
+}
+
+static uint32_t gpe_ioport_readb(struct ich9_lpc_pm_regs *pm,
+                                 uint32_t addr)
+{
+    uint8_t *cur = gpe_ioport_get_ptr(pm, addr);
+    uint32_t val = 0;
+
+    if (cur != NULL)
+        val = *cur;
+
+    ICH9_DEBUG("%x == %x\n", addr, val);
+    return val;
+}
+
+#define PCI_HP_BASE     0xae00
+#define PCI_EJ_BASE     0xae08
+#define PCI_HP_BUS      0xae0c
+
+static uint32_t pcihotplug_read(void *opaque, uint32_t addr)
+{
+    uint32_t val = 0;
+    struct ich9_pci_status *p = opaque;
+    switch (addr) {
+        case PCI_HP_BASE:
+            val = p->up[p->bus];
+            break;
+        case PCI_HP_BASE + 4:
+            val = p->down[p->bus];
+            break;
+        default:
+            break;
+    }
+
+    ICH9_DEBUG("%x == %x\n", addr, val);
+    return val;
+}
+
+static void pcihotplug_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    struct ich9_pci_status *p = opaque;
+    switch (addr) {
+        case PCI_HP_BASE:
+            p->up[p->bus] = val;
+            break;
+        case PCI_HP_BASE + 4:
+            p->down[p->bus] = val;
+            break;
+   }
+
+    ICH9_DEBUG("%x <== %d\n", addr, val);
+}
+
+static uint32_t pciej_read(void *opaque, uint32_t addr)
+{
+    ICH9_DEBUG("%x\n", addr);
+    return 0;
+}
+
+static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
+{
+#if defined (TARGET_I386)
+    struct ich9_pci_status *p = opaque;
+    int slot = ffs(val) - 1;
+
+    pci_device_hot_remove_success(p->bus, slot);
+#endif
+
+    ICH9_DEBUG("%x <== %d\n", addr, val);
+}
+
+static uint32_t pci_hp_bus_read(void *opaque, uint32_t addr)
+{
+    struct ich9_pci_status *p = opaque;
+    ICH9_DEBUG("%x <== %d\n", addr, val);
+    return p->bus;
+}
+
+static void pci_hp_bus_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    struct ich9_pci_status *p = opaque;
+    p->bus = val;
+    ICH9_DEBUG("%x <== %d\n", addr, val);
+}
+
+static void enable_device(struct ich9_pci_status *p, int bus, int slot)
+{
+    p->up[bus] |= (1 << slot);
+}
+
+static void disable_device(struct ich9_pci_status *p, int bus, int slot)
+{
+    p->down[bus] |= (1 << slot);
+}
+
+#define ACPI_SCI_L1 0x2
+
+static void ich9_device_hot_add(int bus, int slot, int state, void *opaque)
+{
+    struct ich9_lpc_pm_regs *pm = opaque;
+    struct ich9_pci_status *pci_status = pm->pci_status;
+
+    pci_status->up[bus] = 0;
+    pci_status->down[bus] = 0;
+
+    if (state)
+        enable_device(pci_status, bus, slot);
+    else
+        disable_device(pci_status, bus, slot);
+
+    pm->gpe0_sts |= ACPI_SCI_L1;
+    if (pm->gpe0_en & ACPI_SCI_L1) {
+        qemu_set_irq(pm->irq, 1);
+        qemu_set_irq(pm->irq, 0);
+    }
+}
+
+void ich9_hot_add_init(struct ich9_lpc_pm_regs *pm)
+{
+    struct ich9_pci_status *pci_status;
+    pci_status = qemu_mallocz(sizeof(*pci_status));
+
+    register_ioport_write(PCI_HP_BASE, 8, 4, pcihotplug_write, pci_status);
+    register_ioport_read(PCI_HP_BASE, 8, 4,  pcihotplug_read, pci_status);
+
+    register_ioport_write(PCI_EJ_BASE, 4, 4, pciej_write, pci_status);
+    register_ioport_read(PCI_EJ_BASE, 4, 4,  pciej_read, pci_status);
+
+    register_ioport_write(PCI_HP_BUS, 1, 1, pci_hp_bus_write, pci_status);
+    register_ioport_read(PCI_HP_BUS, 1, 1,  pci_hp_bus_read, pci_status);
+
+    pm->pci_status = pci_status;
+    qemu_system_device_hot_add_register(ich9_device_hot_add, pm);
+}
diff --git a/hw/acpi_ich9.h b/hw/acpi_ich9.h
new file mode 100644
index 0000000..7ebb710
--- /dev/null
+++ b/hw/acpi_ich9.h
@@ -0,0 +1,57 @@
+/*
+ * QEMU GMCH/ICH9 LPC PM Emulation
+ *
+ *  Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ *                     VA Linux Systems Japan K.K.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * 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 Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+
+#ifndef HW_ACPI_ICH9_H
+#define HW_ACPI_ICH9_H
+
+#include <stdint.h>
+
+struct ich9_pci_status;
+
+struct ich9_lpc_pm_regs {
+    uint16_t pm1_sts;
+    uint16_t pm1_en;
+
+    /*
+     * In ich9 spec says that pm1_cnt register is 32bit width and
+     * that the upper 16bits are reserved and unused.
+     * PM1a_CNT_BLK = 2 in FADT so it is defined as uint16_t.
+     */
+    uint16_t pm1_cnt;
+
+    /* uint32_t pm1_tmr; */
+    QEMUTimer *tmr_timer;
+    int64_t tmr_overflow_time;
+
+    uint64_t gpe0_sts;
+    uint64_t gpe0_en;
+
+    uint32_t smi_en;
+    uint32_t smi_sts;
+
+    qemu_irq irq;      /* SCI */
+
+    uint32_t pm_io_base;
+
+    struct ich9_pci_status *pci_status;
+};
+
+#endif /* HW_ACPI_ICH9_H */
diff --git a/hw/pc_q35.c b/hw/pc_q35.c
new file mode 100644
index 0000000..9980a39
--- /dev/null
+++ b/hw/pc_q35.c
@@ -0,0 +1,220 @@
+/*
+ *  Q35 chipset based pc system emulator
+ *
+ *  Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ *                     VA Linux Systems Japan K.K.
+ *
+ *  This is based on pc.c, but heavily modified.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * 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 Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+/*
+ * QEMU PC System Emulator
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "hw.h"
+#include "pc.h"
+#include "fdc.h"
+#include "pci.h"
+#include "pci_bridge.h"
+#include "block.h"
+#include "sysemu.h"
+#include "audio/audio.h"
+#include "net.h"
+#include "smbus.h"
+#include "boards.h"
+#include "monitor.h"
+#include "fw_cfg.h"
+#include "hpet_emul.h"
+#include "watchdog.h"
+#include "smbios.h"
+#include "ide.h"
+
+#include "q35.h"
+
+#define MAX_IDE_BUS 2
+
+static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 };
+static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 };
+static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
+
+static void pc_q35_bridge_init(PCIBus *host_bus, PCIBus *pci_bus)
+{
+    int dev;
+
+    /* PCI to PCI bridge b6:d[29 - 31]:f0, 6:[1d - 1f].0 with subordinate bus
+       of 7 - 9 on b0:d30:f0, 0.1e.0 = pci_bus */
+#define Q35_P2P_BRDIGE_DEV_BASE         29
+#define Q35_P2P_BRDIGE_DEV_MAX          32
+#define Q35_P2P_BRDIGE_SUBBUS_BASE      7
+    for (dev = Q35_P2P_BRDIGE_DEV_BASE; dev < Q35_P2P_BRDIGE_DEV_MAX; dev++) {
+        int sec_bus =
+            Q35_P2P_BRDIGE_SUBBUS_BASE + dev - Q35_P2P_BRDIGE_DEV_BASE;
+        int sub_bus = sec_bus;
+
+        i82801ba11_init(pci_bus, PCI_DEVFN(dev, 0), sec_bus, sub_bus);
+    }
+
+    /* PCIe root port b0:d1:f0, 0:01.0 with subordinate bus of 63 */
+
+    /* PCIe root port b0:d23:f[0-5], 0.17.[0-5] with subordinate bus of 64 */
+
+    /* PCIe upstream port b0:d24:f0, 0.18.0 with subordinate bus of 126 */
+
+    /* PCIe downstream port b126:d[0-15]:f[0-7], 7e:[0-1f].[0-7] with
+       subordinate bus of 127 - 127 + 128 on bus 126 */
+}
+
+/* PC hardware initialisation */
+static void pc_q35_init(ram_addr_t ram_size,
+                        const char *boot_device,
+                        const char *kernel_filename,
+                        const char *kernel_cmdline,
+                        const char *initrd_filename,
+                        const char *cpu_model)
+{
+    int i;
+    ram_addr_t below_4g_mem_size, above_4g_mem_size;
+    PCIBus *host_bus;
+    PCIBus *pci_bus;
+    ISADevice *isa_dev;
+    static PCIDevice *gmch_state;
+    int ich9_lpc_devfn = -1;
+    qemu_irq *cpu_irq;
+    qemu_irq *isa_irq;
+    qemu_irq *i8259;
+    IsaIrqState *isa_irq_state;
+    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
+    fdctrl_t *floppy_controller;
+    RTCState *rtc_state;
+
+    pc_cpus_init(cpu_model);
+
+    vmport_init();
+
+    /* allocate ram and load rom/bios */
+    pc_memory_init(ram_size, kernel_filename, kernel_cmdline, initrd_filename,
+                   &below_4g_mem_size, &above_4g_mem_size);
+
+
+    cpu_irq = pc_allocate_cpu_irq();
+    i8259 = i8259_init(cpu_irq[0]);
+    isa_irq_state = qemu_mallocz(sizeof(*isa_irq_state));
+    isa_irq_state->i8259 = i8259;
+    isa_irq_state->ioapic = ioapic_init();
+    isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24);
+
+    host_bus = gmch_init(&gmch_state, isa_irq, &ich9_lpc_devfn);
+
+    isa_bus_irqs(isa_irq);
+    pc_register_ferr_irq(isa_reserve_irq(13));
+
+    pci_bus = ich9_d2pbr_init(host_bus, PCI_DEVFN(ICH9_D2P_BRIDGE_DEV,
+                                                  ICH9_D2P_BRIDGE_FUNC),
+                              ICH9_D2P_SECONDARY_DEFAULT);
+    pci_set_default_bus(pci_bus);
+
+    pc_vga_init(host_bus);
+
+    /* init basic PC hardware */
+    pc_basic_device_init(isa_irq, &isa_dev, &floppy_controller, &rtc_state);
+
+    pc_q35_bridge_init(host_bus, pci_bus);
+
+    for(i = 0; i < nb_nics; i++) {
+        NICInfo *nd = &nd_table[i];
+
+        pci_nic_init(nd, "e1000", NULL);
+    }
+
+    if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
+        fprintf(stderr, "qemu: too many IDE bus\n");
+        exit(1);
+    }
+
+    for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
+        hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
+    }
+
+    /* XXX ich9 supports only SATA */
+    pci_piix3_ide_init(pci_bus, hd, -1);
+
+#ifdef HAS_AUDIO
+    pc_audio_init(pci_bus, isa_irq);
+#endif
+
+    pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd,
+                 floppy_controller, rtc_state);
+
+    if (usb_enabled) {
+        /* XXX: make ich9 specific add usb_uchi_ich9_init() */
+        usb_uhci_piix4_init(pci_bus, -1);
+    }
+
+    if (acpi_enabled) {
+        uint8_t *eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
+        i2c_bus *smbus;
+
+        /* TODO: Populate SPD eeprom data.  */
+        /* XXX determine proper smb_io_base */
+        smbus = ich9_smb_init(host_bus, ich9_lpc_devfn + 3, 0xb100);
+        for (i = 0; i < 8; i++) {
+            DeviceState *eeprom;
+            eeprom = qdev_create((BusState *)smbus, "smbus-eeprom");
+            qdev_prop_set_uint32(eeprom, "address", 0x50 + i);
+            qdev_prop_set_ptr(eeprom, "data", eeprom_buf + (i * 256));
+            qdev_init(eeprom);
+        }
+    }
+
+    if (gmch_state) {
+        gmch_init_memory_mappings(gmch_state);
+    }
+
+    pc_pci_device_init(pci_bus);
+}
+
+static QEMUMachine pc_q35_machine = {
+    .name = "pc_q35",
+    .desc = "Q35 chipset PC",
+    .init = pc_q35_init,
+    .max_cpus = 255,
+};
+
+static void pc_q35_machine_init(void)
+{
+    qemu_register_machine(&pc_q35_machine);
+}
+
+machine_init(pc_q35_machine_init);
diff --git a/hw/pci_ids.h b/hw/pci_ids.h
index 7eef2cd..4eb6d07 100644
--- a/hw/pci_ids.h
+++ b/hw/pci_ids.h
@@ -33,6 +33,7 @@
 #define PCI_CLASS_BRIDGE_HOST            0x0600
 #define PCI_CLASS_BRIDGE_ISA             0x0601
 #define PCI_CLASS_BRIDGE_PCI             0x0604
+#define  PCI_CLASS_BRDIGE_PCI_INF_SUB    0x01
 #define PCI_CLASS_BRIDGE_OTHER           0x0680
 
 #define PCI_CLASS_COMMUNICATION_OTHER    0x0780
@@ -109,4 +110,16 @@
 #define PCI_DEVICE_ID_INTEL_82371AB_2    0x7112
 #define PCI_DEVICE_ID_INTEL_82371AB_3    0x7113
 
+#define PCI_DEVICE_ID_INTEL_ICH9_0       0x2910
+#define PCI_DEVICE_ID_INTEL_ICH9_1       0x2917
+#define PCI_DEVICE_ID_INTEL_ICH9_2       0x2912
+#define PCI_DEVICE_ID_INTEL_ICH9_3       0x2913
+#define PCI_DEVICE_ID_INTEL_ICH9_4       0x2914
+#define PCI_DEVICE_ID_INTEL_ICH9_5       0x2919
+#define PCI_DEVICE_ID_INTEL_ICH9_6       0x2930
+#define PCI_DEVICE_ID_INTEL_ICH9_7       0x2916
+#define PCI_DEVICE_ID_INTEL_ICH9_8       0x2918
+
+#define PCI_DEVICE_ID_INTEL_Q35_MCH      0x29c0
+
 #define PCI_VENDOR_ID_INVALID            0xffff
diff --git a/hw/q35.c b/hw/q35.c
new file mode 100644
index 0000000..8e07048
--- /dev/null
+++ b/hw/q35.c
@@ -0,0 +1,731 @@
+/*
+ * QEMU GMCH/ICH9 PCI Bridge Emulation
+ *
+ *  Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ *                     VA Linux Systems Japan K.K.
+ *
+ *  This is based on piix_pci.c, but heavily modified.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * 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 Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+/*
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw.h"
+#include "isa.h"
+#include "sysbus.h"
+#include "pc.h"
+#include "pc_apm.h"
+#include "pci.h"
+#include "pci_bridge.h"
+#include "q35.h"
+#include "acpi.h"
+
+typedef uint32_t pci_addr_t;
+#include "pci_host_c.h"
+
+struct ICH9_LPCState {
+    /* ICH9 LPC PCI to ISA bridge */
+    PCIDevice d;
+
+    int pci_irq_levels[ICH9_LPC_NB_PIRQS];
+
+    APMState apm;
+    struct ich9_lpc_pm_regs pm;
+};
+
+struct ICH9_LPCIrqState {
+    struct ICH9_LPCState *lpc;
+    qemu_irq *pic;
+};
+
+typedef struct GMCHState {
+    PCIExpressHost      host;
+
+    struct PCIDevice    *dev;
+} GMCHState;
+
+struct GMCH_PCIState {
+    PCIDevice   d;
+    //GMCHState   *gmch;
+    // PCIDevice -> qdev -> parent_bus -upcast-> GMCHState
+
+    target_phys_addr_t  isa_page_descs[384 / 4];
+    uint8_t             smm_enabled;
+
+    struct ICH9_LPCIrqState *irq_state;
+};
+
+static GMCHState *gmchstate_from_sysbus(SysBusDevice *dev)
+{
+    PCIHostState *pci = FROM_SYSBUS(PCIHostState, dev);
+    PCIExpressHost *pcie = DO_UPCAST(PCIExpressHost, pci, pci);
+    return DO_UPCAST(GMCHState, host, pcie);
+}
+
+/* pci */
+static void gmch_addr_writel(void* opaque, uint32_t addr, uint32_t val)
+{
+    GMCHState *s = opaque;
+    s->host.pci.config_reg = val;
+}
+
+static uint32_t gmch_addr_readl(void* opaque, uint32_t addr)
+{
+    GMCHState *s = opaque;
+    return s->host.pci.config_reg;
+}
+
+/* PCIE MMCFG */
+static void gmch_update_pcixbar(struct GMCH_PCIState *gs)
+{
+    PCIDevice* pci_dev = &gs->d;
+    BusState *bus = qdev_get_parent_bus(&pci_dev->qdev);
+    DeviceState *qdev = bus->parent;
+    GMCHState *s = gmchstate_from_sysbus(sysbus_from_qdev(qdev));
+
+    uint64_t pciexbar;
+    int enable;
+    uint64_t addr;
+    uint64_t addr_mask;
+    uint32_t length;
+
+    pciexbar = pci_config_get_quad(pci_dev, Q35_HOST_BRIDGE_PCIEXBAR);
+    enable = pciexbar & Q35_HOST_BRIDGE_PCIEXBAREN;
+
+    addr_mask = Q35_HOST_BRIDGE_PCIEXBAR_ADMSK;
+    switch (pciexbar & Q35_HOST_BRIDGE_PCIEXBAR_LENGTH_MASK) {
+    case Q35_HOST_BRIDGE_PCIEXBAR_LENGTH_256M:
+        length = 256 * 1024 * 1024;
+        break;
+    case Q35_HOST_BRIDGE_PCIEXBAR_LENGTH_128M:
+        length = 128 * 1024 * 1024;
+        addr_mask |= Q35_HOST_BRIDGE_PCIEXBAR_128ADMSK |
+            Q35_HOST_BRIDGE_PCIEXBAR_64ADMSK;
+        break;
+    case Q35_HOST_BRIDGE_PCIEXBAR_LENGTH_64M:
+        length = 64 * 1024 * 1024;
+        addr_mask |= Q35_HOST_BRIDGE_PCIEXBAR_64ADMSK;
+        break;
+    case Q35_HOST_BRIDGE_PCIEXBAR_LENGTH_RVD:
+    default:
+        enable = 0;
+        length = 0;
+        abort();
+        break;
+    }
+    addr = pciexbar & addr_mask;
+
+    pcie_host_mmcfg_update(&s->host, enable, addr, length);
+}
+
+/* ich9 irq */
+static struct ICH9_LPCState *ich9_lpc_init(PCIBus *bus, int devfn, struct ICH9_LPCIrqState *irq_state);
+static void ich9_lpc_set_irq(void *opaque, int irq_num, int level);
+
+/* return the global irq number corresponding to a given device irq
+   pin. We could also use the bus number to have a more precise
+   mapping. */
+static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
+{
+    return pci_swizzle_map_irq_fn(pci_dev, irq_num);
+}
+
+/* PAM */
+
+/* XXX: suppress when better memory API. We make the assumption that
+   no device (in particular the VGA) changes the memory mappings in
+   the 0xa0000-0x100000 =
+   [Q35_HOST_BRIDGE_SMARM_C_BASE, Q35_HOST_BRIDGE_UPPER_SYSTEM_BIOS_END)
+   range */
+void gmch_init_memory_mappings(PCIDevice *d)
+{
+    struct GMCH_PCIState *gs = DO_UPCAST(struct GMCH_PCIState, d, d);
+    int i;
+    for(i = 0; i < 96; i++) {
+        gs->isa_page_descs[i] = cpu_get_physical_page_desc(
+            Q35_HOST_BRIDGE_SMARM_C_BASE + i * 0x1000);
+    }
+}
+
+static target_phys_addr_t isa_page_descs_get(struct GMCH_PCIState *gs,
+                                             uint32_t addr)
+{
+    return gs->isa_page_descs[
+        (addr - Q35_HOST_BRIDGE_SMARM_C_BASE) >> TARGET_PAGE_BITS];
+}
+
+static void update_pam(struct GMCH_PCIState *gs,
+                       uint32_t start, uint32_t size, uint8_t r)
+{
+    uint32_t addr;
+
+#if 0
+    printf("ISA mapping %08"PRIx32"-0x%08"PRIx32": %"PRId32"\n",
+           start, start + size, r);
+#endif
+    switch(r) {
+    case Q35_HOST_BRIDGE_PAM_WE | Q35_HOST_BRIDGE_PAM_RE:
+        /* RAM */
+        cpu_register_physical_memory(start, size, start);
+        break;
+
+    case Q35_HOST_BRIDGE_PAM_RE:
+        /* ROM (XXX: not quite correct) */
+        cpu_register_physical_memory(start, size, start | IO_MEM_ROM);
+        break;
+
+    case Q35_HOST_BRIDGE_PAM_WE:
+    case 0:
+        /* XXX: should distinguish read/write cases */
+        for(addr = start; addr < start + size; addr += TARGET_PAGE_SIZE) {
+            cpu_register_physical_memory(addr, TARGET_PAGE_SIZE,
+                                         isa_page_descs_get(gs, addr));
+        }
+        break;
+
+    default:
+        abort();
+        break;
+    }
+}
+
+static uint8_t gmch_get_pam_attr(PCIDevice *d, uint32_t addr, int hi)
+{
+    return (d->config[addr] >> ((!!hi) * 4)) & Q35_HOST_BRIDGE_PAM_MASK;
+}
+
+static void gmch_update_pam(struct GMCH_PCIState *gs, int pam)
+{
+    PCIDevice *d = &gs->d;
+    uint32_t conf_addr = Q35_HOST_BRIDGE_PAM0 + pam;
+    uint32_t phys_addr;
+
+    assert(0 <= pam && pam <= 6);
+
+    if (pam == 0) {
+        update_pam(gs, Q35_HOST_BRIDGE_PAM_BIOS_AREA,
+                   Q35_HOST_BRIDGE_PAM_AREA_SIZE,
+                   gmch_get_pam_attr(d, conf_addr, 1));
+        return;
+    }
+
+    phys_addr = Q35_HOST_BRIDGE_PAM_EXPAN_AREA +
+        Q35_HOST_BRIDGE_PAM_EXPAN_SIZE * (pam - 1) * 2;
+    update_pam(gs, phys_addr, Q35_HOST_BRIDGE_PAM_EXPAN_SIZE,
+               gmch_get_pam_attr(d, conf_addr, 0));
+
+    phys_addr += Q35_HOST_BRIDGE_PAM_AREA_SIZE;
+    update_pam(gs, phys_addr, Q35_HOST_BRIDGE_PAM_EXPAN_SIZE,
+               gmch_get_pam_attr(d, conf_addr, 1));
+}
+
+static void gmch_update_memory_mappings(struct GMCH_PCIState *gs)
+{
+    int i;
+
+    for (i = 0; i < Q35_HOST_BRIDGE_PAM_NB; i++)
+        gmch_update_pam(gs, i);
+}
+
+/* SMRAM */
+static void gmch_update_smram(struct GMCH_PCIState *gs)
+{
+    uint32_t smram;
+    uint32_t addr;
+
+    smram = gs->d.config[Q35_HOST_BRDIGE_SMRAM];
+    if ((gs->smm_enabled && (smram & Q35_HOST_BRIDGE_SMRAM_G_SMRAME)) ||
+        (smram & Q35_HOST_BRIDGE_SMRAM_D_OPEN)) {
+        cpu_register_physical_memory(Q35_HOST_BRIDGE_SMARM_C_BASE,
+                                     Q35_HOST_BRIDGE_SMRAM_C_SIZE,
+                                     Q35_HOST_BRIDGE_SMARM_C_BASE);
+    } else {
+        for(addr = Q35_HOST_BRIDGE_SMARM_C_BASE;
+            addr < Q35_HOST_BRIDGE_SMRAM_C_END;
+            addr += TARGET_PAGE_SIZE) {
+            cpu_register_physical_memory(addr, TARGET_PAGE_SIZE,
+                                         isa_page_descs_get(gs, addr));
+        }
+    }
+}
+
+static void gmch_set_smm(int smm, void *arg)
+{
+    uint8_t val = (smm != 0);
+    struct GMCH_PCIState *gs = (struct GMCH_PCIState*)arg;
+
+    if (gs->smm_enabled != val) {
+        gs->smm_enabled = val;
+        gmch_update_smram(gs);
+    }
+}
+
+static void gmch_write_config(PCIDevice *d,
+                                uint32_t address, uint32_t val, int len)
+{
+    struct GMCH_PCIState *gs = DO_UPCAST(struct GMCH_PCIState, d, d);
+
+    /* XXX: implement SMRAM.D_LOCK */
+    pci_default_write_config(d, address, val, len);
+
+    if (pci_config_changed(address, len,
+                           Q35_HOST_BRIDGE_PAM0, Q35_HOST_BRIDGE_PAM6))
+        gmch_update_memory_mappings(gs);
+
+    if (pci_config_changed_with_size(address, len, Q35_HOST_BRIDGE_PCIEXBAR,
+                                     Q35_HOST_BRIDGE_PCIEXBAR_SIZE))
+        gmch_update_pcixbar(gs);
+
+    if (pci_config_changed_with_size(address, len, Q35_HOST_BRDIGE_SMRAM,
+                                     Q35_HOST_BRDIGE_SMRAM_SIZE))
+        gmch_update_smram(gs);
+}
+
+static int gmch_post_load(void *opaque)
+{
+    struct GMCH_PCIState *gs = opaque;
+    gmch_update_memory_mappings(gs);
+    gmch_update_smram(gs);
+    return 0;
+}
+
+static const VMStateDescription vmstate_gmch = {
+    .name = "gmch",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .post_load = gmch_post_load,
+    .fields = (VMStateField []) {
+        VMSTATE_PCI_DEVICE(d, struct GMCH_PCIState),
+        VMSTATE_UINT8(smm_enabled, struct GMCH_PCIState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static int gmch_pcihost_initfn(SysBusDevice *dev)
+{
+    GMCHState *s = gmchstate_from_sysbus(dev);
+
+    register_ioport_write(Q35_HOST_BRIDGE_CONFIG_ADDR,
+                          4, 4, gmch_addr_writel, s);
+    register_ioport_read(Q35_HOST_BRIDGE_CONFIG_ADDR,
+                         4, 4, gmch_addr_readl, s);
+
+    register_ioport_write(Q35_HOST_BRIDGE_CONFIG_DATA,
+                          4, 1, pci_host_data_writeb, s);
+    register_ioport_write(Q35_HOST_BRIDGE_CONFIG_DATA,
+                          4, 2, pci_host_data_writew, s);
+    register_ioport_write(Q35_HOST_BRIDGE_CONFIG_DATA,
+                          4, 4, pci_host_data_writel, s);
+    register_ioport_read(Q35_HOST_BRIDGE_CONFIG_DATA,
+                         4, 1, pci_host_data_readb, s);
+    register_ioport_read(Q35_HOST_BRIDGE_CONFIG_DATA,
+                         4, 2, pci_host_data_readw, s);
+    register_ioport_read(Q35_HOST_BRIDGE_CONFIG_DATA,
+                         4, 4, pci_host_data_readl, s);
+
+    if (pcie_host_init(&s->host, NULL, NULL) < 0)
+        abort();
+
+    return 0;
+}
+
+static int gmch_initfn(PCIDevice *d)
+{
+    struct GMCH_PCIState *gs = DO_UPCAST(struct GMCH_PCIState, d, d);
+
+    pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_INTEL);
+    pci_config_set_device_id(d->config, PCI_DEVICE_ID_INTEL_Q35_MCH);
+    d->config[PCI_REVISION_ID] = Q35_HOST_BRIDGE_REVISION_DEFUALT;
+    pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
+    d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL;
+
+    pci_config_set_quad(d, Q35_HOST_BRIDGE_PCIEXBAR,
+                        Q35_HOST_BRIDGE_PCIEXBAR_DEFAULT);
+    gmch_update_pcixbar(gs);
+
+    d->config[Q35_HOST_BRDIGE_SMRAM] = Q35_HOST_BRIDGE_SMRAM_DEFAULT;
+
+    vmstate_register(0, &vmstate_gmch, gs);
+    cpu_smm_register(&gmch_set_smm, gs);
+
+    return 0;
+}
+
+/* host bridge */
+PCIBus *gmch_init(PCIDevice **pgmch_state, qemu_irq *pic, int *ich9_lpc_devfn)
+{
+    DeviceState *dev;
+    GMCHState *s;
+    PCIBus *b;
+    PCIDevice *d;
+    struct GMCH_PCIState *gs;
+    struct ICH9_LPCIrqState *irq_state = qemu_malloc(sizeof(*irq_state));
+
+    irq_state->pic = pic;
+    dev = qdev_create(NULL, "gmch-pcihost");
+    s = gmchstate_from_sysbus(sysbus_from_qdev(dev));
+    b = pci_register_bus(dev, "pci.0",
+                         ich9_lpc_set_irq, pci_slot_get_pirq, irq_state, 0,
+                         24 /* 24 pin IO APIC */);
+    s->host.pci.bus = b;
+    qdev_init(dev);
+
+    d = pci_create_simple(b, 0, "gmch");
+    s->dev = d;
+    gs = DO_UPCAST(struct GMCH_PCIState, d, d);
+    gs->irq_state = irq_state;
+    *pgmch_state = d;
+
+    irq_state->lpc = ich9_lpc_init(b, PCI_DEVFN(ICH9_LPC_DEV, ICH9_LPC_FUNC),
+                                   irq_state);
+    *ich9_lpc_devfn = irq_state->lpc->d.devfn;
+    return b;
+}
+
+static SysBusDeviceInfo gmch_pcihost_info = {
+    .init         = gmch_pcihost_initfn,
+    .qdev.name    = "gmch-pcihost",
+    .qdev.size    = sizeof(GMCHState),
+    .qdev.no_user = 1,
+    .qdev.props = (Property[]) {
+        {
+            .name = "MCFG",
+            .info = &qdev_prop_uint64,
+            .offset = offsetof(GMCHState, host.base_addr),
+            .defval = (uint64_t[]){ Q35_HOST_BRIDGE_PCIEXBAR_DEFAULT },
+        },
+        {/* end of list */}
+    },
+};
+
+static PCIDeviceInfo gmch_info = {
+    .qdev.name    = "gmch",
+    .qdev.desc    = "Host bridge",
+    .qdev.size    = sizeof(struct GMCH_PCIState),
+    .qdev.no_user = 1,
+    .init         = gmch_initfn,
+    .config_write = gmch_write_config,
+};
+
+static void gmch_register(void)
+{
+    sysbus_register_withprop(&gmch_pcihost_info);
+    pci_qdev_register(&gmch_info);
+}
+device_init(gmch_register);
+
+/*****************************************************************************/
+/* ICH9 DMI-to-PCI bridge */
+static void ich9_d2pbr_reset(PCIDevice *d)
+{
+    pci_config_set_word(d, PCI_COMMAND,
+                        PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+                        PCI_COMMAND_MASTER);
+    pci_config_set_word(d, PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM);
+}
+
+PCIBus *ich9_d2pbr_init(PCIBus *bus, int devfn, int secondary_bus_num)
+{
+    PCIBus *b;
+    PCIDevice *d;
+
+    b = pci_bridge_create_simple(bus, devfn,
+                                 PCI_VENDOR_ID_INTEL,
+                                 PCI_DEVICE_ID_INTEL_82801BA_11,
+                                 secondary_bus_num,
+                                 secondary_bus_num,
+                                 pci_swizzle_map_irq_fn,
+                                 "Intel ich9 dmi to pci bridge",
+                                 PCI_BRIDGE_INTEL_82801BA_11);
+    if (b == NULL)
+        return NULL;
+
+    d = pci_bus_to_dev(b);
+    vmstate_register(0, &vmstate_pci_device, d); /* current s2pbr doesn't have
+                                                    specfic bridge status */
+
+
+    /* some command bits are hotwired to 0 for pcie */
+    pci_conf_initw(d, PCI_COMMAND,
+                   PCI_COMMAND_IO |
+                   PCI_COMMAND_MEMORY |
+                   PCI_COMMAND_MASTER |
+                   PCI_COMMAND_PARITY |
+                   PCI_COMMAND_SERR);
+
+    pci_config_set_byte(d, PCI_REVISION_ID, ICH9_D2P_A2_REVISION);
+
+    // XXX
+    pci_config_set_byte(d, PCI_CLASS_PROG, PCI_CLASS_BRDIGE_PCI_INF_SUB);
+    pci_config_set_byte(d, PCI_HEADER_TYPE, PCI_HEADER_TYPE_BRIDGE);
+
+    ich9_d2pbr_reset(d);
+    return b;
+}
+
+
+/*****************************************************************************/
+/* ICH9 LPC PCI to ISA bridge */
+
+static struct ICH9_LPCState *ich9_pci_to_lpc(PCIDevice *d)
+{
+    return DO_UPCAST(struct ICH9_LPCState, d, d);
+}
+
+static void ich9_lpc_reset(struct ICH9_LPCState *lpc)
+{
+    PCIDevice *d = &lpc->d;
+    int i;
+
+    pci_config_set_word(d, PCI_COMMAND,
+                        PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+                        PCI_COMMAND_MASTER);
+
+    /* XXX capability isn't supported yet */
+    pci_config_set_word(d, PCI_STATUS,
+                        PCI_STATUS_DEVSEL_MEDIUM /* | PCI_STATUS_CAP_LIST */);
+
+    for (i = 0; i < 4; i++) {
+        pci_config_set_byte(d, ICH9_LPC_PIRQA_ROUT + i,
+                            ICH9_LPC_PIRQ_ROUT_DEFAULT);
+    }
+    for (i = 0; i < 4; i++) {
+        pci_config_set_byte(d, ICH9_LPC_PIRQE_ROUT + i,
+                            ICH9_LPC_PIRQ_ROUT_DEFAULT);
+    }
+    pci_config_set_long(d, ICH9_LPC_PMBASE, ICH9_LPC_PMBASE_DEFAULT);
+    pci_config_set_long(d, ICH9_LPC_RCBA, ICH9_LPC_RCBA_DEFAULT);
+}
+
+static void ich9_lpc_rout(uint8_t pirq_rout, int *pic_irq, int *pic_dis)
+{
+    *pic_irq = pirq_rout & ICH9_LPC_PIRQ_ROUT_MASK;
+    *pic_dis = pirq_rout & ICH9_LPC_PIRQ_ROUT_IRQEN;
+}
+
+static void ich9_lpc_pic_irq(struct ICH9_LPCState *lpc, int irq_num,
+                             int *pic_irq, int *pic_dis)
+{
+    switch (irq_num) {
+    case 0 ... 3: /* A-D */
+        ich9_lpc_rout(lpc->d.config[ICH9_LPC_PIRQA_ROUT + irq_num],
+                      pic_irq, pic_dis);
+        return;
+    case 4 ... 7: /* E-H */
+        ich9_lpc_rout(lpc->d.config[ICH9_LPC_PIRQE_ROUT + (irq_num - 4)],
+                      pic_irq, pic_dis);
+        return;
+    default:
+        break;
+    }
+    abort();
+}
+
+static void ich9_lpc_set_irq(void *opaque, int irq_num, int level)
+{
+    struct ICH9_LPCIrqState *irq_state = opaque;
+    struct ICH9_LPCState *ich9_lpc = irq_state->lpc;
+    qemu_irq *pic = irq_state->pic;
+    int i, pic_level;
+    int pic_irq;
+    int pic_dis;
+
+    assert(0 <= irq_num && irq_num < 8);
+    ich9_lpc->pci_irq_levels[irq_num] = level;
+
+    /* now we change the pic irq level according to
+       the ich9 lpc irq mappings */
+    ich9_lpc_pic_irq(ich9_lpc, irq_num, &pic_irq, &pic_dis);
+    if (pic_dis) {
+        return;
+    }
+
+    if (pic_irq > 24) {
+        fprintf(stderr, "%s: error irq_num %d pic_irq %d\n",
+                __func__, irq_num, pic_irq);
+        return;
+    }
+
+    /* The pic level is the logical OR of all the PCI irqs mapped to it */
+    pic_level = 0;
+    for (i = 0; i < ICH9_LPC_NB_PIRQS; i++) {
+        int tmp_irq;
+        int tmp_dis;
+        ich9_lpc_pic_irq(ich9_lpc, i, &tmp_irq, &tmp_dis);
+        if (!tmp_dis && pic_irq == tmp_irq) {
+            pic_level |= ich9_lpc->pci_irq_levels[i];
+        }
+    }
+    qemu_set_irq(pic[pic_irq], pic_level);
+}
+
+/* APM */
+static void ich9_apm_ctrl_changed(uint32_t val, void *arg)
+{
+    struct ICH9_LPCState *lpc = arg;
+
+    /* ACPI specs 3.0, 4.7.2.5 */
+    if (val == ICH9_APM_ACPI_ENABLE) {
+        lpc->pm.pm1_cnt |= ACPI_BITMASK_SCI_ENABLE;
+    } else if (val == ICH9_APM_ACPI_DISABLE) {
+        lpc->pm.pm1_cnt &= ~ACPI_BITMASK_SCI_ENABLE;
+    }
+
+    /* SMI_EN = PMBASE + 30. SMI control and enable register */
+    if (lpc->pm.smi_en & ICH9_PMIO_SMI_EN_APMC_EN) {
+        cpu_interrupt(first_cpu, CPU_INTERRUPT_SMI);
+    }
+}
+
+/* config:PMBASE */
+static void
+ich9_lpc_pmbase_update(PCIDevice *d)
+{
+    uint32_t pm_io_base = pci_config_get_long(d, ICH9_LPC_PMBASE);
+    pm_io_base &= ICH9_LPC_PMBASE_BASE_ADDRESS_MASK;
+
+    ich9_pm_iospace_update(&ich9_pci_to_lpc(d)->pm, pm_io_base);
+}
+
+static int ich9_lpc_post_load(void *opaque)
+{
+    struct ICH9_LPCState *lpc = opaque;
+
+    ich9_lpc_pmbase_update(&lpc->d);
+    return 0;
+}
+
+static const VMStateDescription vmstate_ich9_lpc = {
+    .name = "ICH9LPC",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .post_load = ich9_lpc_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_PCI_DEVICE(d, struct ICH9_LPCState),
+        VMSTATE_INT32_ARRAY(pci_irq_levels, struct ICH9_LPCState,
+                            ICH9_LPC_NB_PIRQS),
+        VMSTATE_STRUCT(apm, struct ICH9_LPCState, 0,
+                       vmstate_pc_apm, APMState),
+        VMSTATE_STRUCT(pm, struct ICH9_LPCState, 0,
+                       vmstate_ich9_pm, struct ich9_lpc_pm_regs),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void ich9_set_sci(void *opaque, int irq_num, int level)
+{
+    /* opaque = pic */
+    assert(irq_num == 0);
+    ich9_lpc_set_irq(opaque, 1/* SCI = PIRQB# */, level);
+}
+
+static qemu_irq *ich9_lpc_allocate_sci_irq(struct ICH9_LPCIrqState *irq_state)
+{
+    return qemu_allocate_irqs(ich9_set_sci, irq_state, 1);
+}
+
+static void ich9_lpc_config_write( PCIDevice *d,
+                                   uint32_t addr, uint32_t val, int len)
+{
+    pci_default_write_config(d, addr, val, len);
+    if (pci_config_changed_with_size(addr, len, ICH9_LPC_PMBASE, 4)) {
+        ich9_lpc_pmbase_update(d);
+    }
+}
+
+static int ich9_lpc_initfn(PCIDevice *d)
+{
+    struct ICH9_LPCState *lpc = ich9_pci_to_lpc(d);
+    //ich9_lpc_set_irq_register(lpc); /* for ich9_lpc_set_irq XXX */
+
+    isa_bus_new(&d->qdev);
+    pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_INTEL);
+    pci_config_set_device_id(d->config, PCI_DEVICE_ID_INTEL_ICH9_8); /* ICH9 LPC */
+    pci_config_set_byte(d, PCI_REVISION_ID, ICH9_A2_LPC_REVISION);
+    pci_config_set_class(d->config, PCI_CLASS_BRIDGE_ISA);
+
+    /* header_type = PCI_multifunction, generic */
+    pci_config_set_byte(d, PCI_HEADER_TYPE,
+                        PCI_HEADER_TYPE_NORMAL |
+                        PCI_HEADER_TYPE_MULTI_FUNCTION);
+
+    apm_init(&lpc->apm, ich9_apm_ctrl_changed, lpc);
+
+
+    pci_conf_initl(d, ICH9_LPC_PMBASE, ICH9_LPC_PMBASE_BASE_ADDRESS_MASK);
+    pci_config_set_long(d, ICH9_LPC_PMBASE, ICH9_LPC_PMBASE_DEFAULT);
+
+    vmstate_register(0, &vmstate_ich9_lpc, lpc);
+
+    return 0;
+}
+
+static struct ICH9_LPCState *
+ich9_lpc_init(PCIBus *bus, int devfn, struct ICH9_LPCIrqState *irq_state)
+{
+    PCIDevice *d;
+    struct ICH9_LPCState *lpc;
+    qemu_irq *sci_irq;
+
+    assert(devfn == PCI_DEVFN(ICH9_LPC_DEV, ICH9_LPC_FUNC));
+    d = pci_create_simple(bus, devfn, "ICH9 LPC");
+    lpc = ich9_pci_to_lpc(d);
+
+    sci_irq = ich9_lpc_allocate_sci_irq(irq_state);
+    ich9_pm_init(&lpc->pm, sci_irq[0]);
+    ich9_lpc_reset(lpc);
+    ich9_hot_add_init(&lpc->pm);
+
+    return lpc;
+}
+
+static PCIDeviceInfo ich9_lpc_info = {
+    .qdev.name    = "ICH9 LPC",
+    .qdev.desc    = "ICH9 LPC bridge",
+    .qdev.size    = sizeof(struct ICH9_LPCState),
+    .qdev.no_user = 1,
+    .init         = ich9_lpc_initfn,
+    .config_write = ich9_lpc_config_write,
+};
+
+
+static void ich9_lpc_register(void)
+{
+    pci_qdev_register(&ich9_lpc_info);
+}
+
+device_init(ich9_lpc_register);
diff --git a/hw/q35.h b/hw/q35.h
new file mode 100644
index 0000000..a3a97b5
--- /dev/null
+++ b/hw/q35.h
@@ -0,0 +1,228 @@
+/*
+ * q35.h
+ *
+ * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef HW_Q35_H
+#define HW_Q35_H
+
+#include "acpi_ich9.h"
+
+void gmch_init_memory_mappings(PCIDevice *d);
+PCIBus *gmch_init(PCIDevice **pgmch_state, qemu_irq *pic, int *ich9_lpc_devfn);
+
+PCIBus *ich9_d2pbr_init(PCIBus *bus, int devfn, int secondary_bus_num);
+
+i2c_bus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base);
+
+void ich9_pm_init(struct ich9_lpc_pm_regs *pm, qemu_irq sci_irq);
+void ich9_pm_iospace_update(struct ich9_lpc_pm_regs *pm, uint32_t pm_io_base);
+extern const VMStateDescription vmstate_ich9_pm;
+
+void ich9_hot_add_init(struct ich9_lpc_pm_regs *pm);
+
+#define Q35_MASK(bit, ms_bit, ls_bit)           ((uint##bit##_t)(((1ULL << ((ms_bit) + 1)) - 1) & ~((1ULL << ls_bit) - 1)))
+
+/*
+ * gmch part
+ */
+
+/* PCI configuration */
+#define Q35_HOST_BRIDGE                         "GMCH"
+
+#define Q35_HOST_BRIDGE_CONFIG_ADDR             0xcf8
+#define Q35_HOST_BRIDGE_CONFIG_DATA             0xcfc
+
+/* D0:F0 configuration space */
+#define  Q35_HOST_BRIDGE_REVISION_DEFUALT       0x0
+
+#define Q35_HOST_BRIDGE_PCIEXBAR                0x60    /* 64bit register */
+#define  Q35_HOST_BRIDGE_PCIEXBAR_SIZE          8       /* 64bit register */
+#define  Q35_HOST_BRIDGE_PCIEXBAR_DEFAULT       0xe0000000
+//#define  Q35_HOST_BRIDGE_PCIEXBAR_DEFAULT       (0xe0000000 | Q35_HOST_BRIDGE_PCIEXBAREN)
+//#define  Q35_HOST_BRIDGE_PCIEXBAR_DEFAULT       (0xf0000000 | Q35_HOST_BRIDGE_PCIEXBAREN)
+//#define  Q35_HOST_BRIDGE_PCIEXBAR_DEFAULT       (0xf4000000 | Q35_HOST_BRIDGE_PCIEXBAREN)
+#define  Q35_HOST_BRIDGE_PCIEXBAR_ADMSK         Q35_MASK(64, 35, 25)    /* bit 35:28 */
+#define  Q35_HOST_BRIDGE_PCIEXBAR_128ADMSK      ((uint64_t)(1 << 26))
+#define  Q35_HOST_BRIDGE_PCIEXBAR_64ADMSK       ((uint64_t)(1 << 25))
+#define  Q35_HOST_BRIDGE_PCIEXBAR_LENGTH_MASK   ((uint64_t)(0x3 << 1))
+#define  Q35_HOST_BRIDGE_PCIEXBAR_LENGTH_256M   ((uint64_t)(0x0 << 1))
+#define  Q35_HOST_BRIDGE_PCIEXBAR_LENGTH_128M   ((uint64_t)(0x1 << 1))
+#define  Q35_HOST_BRIDGE_PCIEXBAR_LENGTH_64M    ((uint64_t)(0x2 << 1))
+#define  Q35_HOST_BRIDGE_PCIEXBAR_LENGTH_RVD    ((uint64_t)(0x3 << 1))
+#define  Q35_HOST_BRIDGE_PCIEXBAREN             ((uint64_t)1)
+
+#define Q35_HOST_BRIDGE_PAM_NB                  7
+#define Q35_HOST_BRIDGE_PAM0                    0x90
+#define  Q35_HOST_BRIDGE_PAM_BIOS_AREA          0xf0000
+#define  Q35_HOST_BRIDGE_PAM_AREA_SIZE          0x10000 /* 16KB */
+#define Q35_HOST_BRIDGE_PAM1                    0x91
+#define  Q35_HOST_BRIDGE_PAM_EXPAN_AREA         0xc0000
+#define  Q35_HOST_BRIDGE_PAM_EXPAN_SIZE         0x04000
+#define Q35_HOST_BRIDGE_PAM2                    0x92
+#define Q35_HOST_BRIDGE_PAM3                    0x93
+#define Q35_HOST_BRIDGE_PAM4                    0x94
+#define  Q35_HOST_BRIDGE_PAM_EXBIOS_AREA        0xe0000
+#define  Q35_HOST_BRIDGE_PAM_EXBIOS_SIZE        0x04000
+#define Q35_HOST_BRIDGE_PAM5                    0x95
+#define Q35_HOST_BRIDGE_PAM6                    0x96
+#define  Q35_HOST_BRIDGE_PAM_WE_HI              ((uint8_t)(0x2 << 4))
+#define  Q35_HOST_BRIDGE_PAM_RE_HI              ((uint8_t)(0x1 << 4))
+#define  Q35_HOST_BRIDGE_PAM_HI_MASK            ((uint8_t)(0x3 << 4))
+#define  Q35_HOST_BRIDGE_PAM_WE_LO              ((uint8_t)0x2)
+#define  Q35_HOST_BRIDGE_PAM_RE_LO              ((uint8_t)0x1)
+#define  Q35_HOST_BRIDGE_PAM_LO_MASK            ((uint8_t)0x3)
+#define  Q35_HOST_BRIDGE_PAM_WE                 ((uint8_t)0x2)
+#define  Q35_HOST_BRIDGE_PAM_RE                 ((uint8_t)0x1)
+#define  Q35_HOST_BRIDGE_PAM_MASK               ((uint8_t)0x3)
+
+
+#define Q35_HOST_BRDIGE_SMRAM                   0x9d
+#define Q35_HOST_BRDIGE_SMRAM_SIZE              1
+#define  Q35_HOST_BRIDGE_SMRAM_DEFAULT          ((uint8_t)0x2)
+#define  Q35_HOST_BRIDGE_SMRAM_D_OPEN           ((uint8_t)(1 << 6))
+#define  Q35_HOST_BRIDGE_SMRAM_D_CLS            ((uint8_t)(1 << 5))
+#define  Q35_HOST_BRIDGE_SMRAM_D_LCK            ((uint8_t)(1 << 4))
+#define  Q35_HOST_BRIDGE_SMRAM_G_SMRAME         ((uint8_t)(1 << 3))
+#define  Q35_HOST_BRIDGE_SMRAM_C_BASE_SEG_MASK  ((uint8_t)0x7)
+#define  Q35_HOST_BRIDGE_SMRAM_C_BASE_SEG       ((uint8_t)0x2)  /* hardwired to b010 */
+#define   Q35_HOST_BRIDGE_SMARM_C_BASE          0xa0000
+#define   Q35_HOST_BRIDGE_SMRAM_C_END           0xc0000
+#define   Q35_HOST_BRIDGE_SMRAM_C_SIZE          0x20000
+#define Q35_HOST_BRIDGE_UPPER_SYSTEM_BIOS_END   0x100000
+
+#define Q35_HOST_BRIDGE_ESMRAMC                 0x9e
+#define  Q35_HOST_BRDIGE_ESMRAMC_H_SMRAME       ((uint8_t)(1 << 6))
+#define  Q35_HOST_BRDIGE_ESMRAMC_E_SMERR        ((uint8_t)(1 << 5))
+#define  Q35_HOST_BRDIGE_ESMRAMC_SM_CACHE       ((uint8_t)(1 << 4))
+#define  Q35_HOST_BRDIGE_ESMRAMC_SM_L1          ((uint8_t)(1 << 3))
+#define  Q35_HOST_BRDIGE_ESMRAMC_SM_L2          ((uint8_t)(1 << 2))
+#define  Q35_HOST_BRDIGE_ESMRAMC_TSEG_SZ_MASK   ((uint8_t)(0x3 << 1))
+#define   Q35_HOST_BRDIGE_ESMRAMC_TSEG_SZ_1MB   ((uint8_t)(0x0 << 1))
+#define   Q35_HOST_BRDIGE_ESMRAMC_TSEG_SZ_2MB   ((uint8_t)(0x1 << 1))
+#define   Q35_HOST_BRDIGE_ESMRAMC_TSEG_SZ_8MB   ((uint8_t)(0x2 << 1))
+#define  Q35_HOST_BRDIGE_ESMRAMC_T_EN           ((uint8_t)1)
+
+
+/*
+ * ich9 part
+ */
+
+/* D30:F0 DMI-to-PCI brdige */
+#define ICH9_D2P_BRIDGE                         "ICH9 D2P BRIDGE"
+#define ICH9_D2P_BRIDGE_SAVEVM_VERSION          0
+
+#define ICH9_D2P_BRIDGE_DEV                     30
+#define ICH9_D2P_BRIDGE_FUNC                    0
+
+/* 1 pcie port on gmch and 6 pcie port on ich9,
+   the next bus # is 7 */
+#define ICH9_D2P_SECONDARY_DEFAULT              6
+
+#define ICH9_D2P_A2_REVISION                    0x92
+
+
+/* D30:F1 LPC controller */
+#define ICH9_A2_LPC                             "ICH9 A2 LPC"
+#define ICH9_A2_LPC_SAVEVM_VERSION              0
+
+#define ICH9_LPC_DEV                            31
+#define ICH9_LPC_FUNC                           0
+
+#define ICH9_A2_LPC_REVISION                    0x2
+#define ICH9_LPC_NB_PIRQS                       8       /* PCI A-H */
+
+#define ICH9_LPC_PMBASE                         0x40
+#define  ICH9_LPC_PMBASE_BASE_ADDRESS_MASK      Q35_MASK(32, 15, 7)
+#define  ICH9_LPC_PMBASE_RTE                    0x1
+#define  ICH9_LPC_PMBASE_DEFAULT                0x1
+#define ICH9_LPC_ACPI_CTRL                      0x44
+#define  ICH9_LPC_ACPI_CTRL_ACPI_EN             0x80
+#define  ICH9_LPC_ACPI_CTRL_SCI_IRQ_SEL_MASK    Q35_MASK(8, 2, 0)
+#define  ICH9_LPC_ACPI_CTRL_DEFAULT             0x0
+
+#define ICH9_LPC_PIRQA_ROUT                     0x60
+#define ICH9_LPC_PIRQB_ROUT                     0x61
+#define ICH9_LPC_PIRQC_ROUT                     0x62
+#define ICH9_LPC_PIRQD_ROUT                     0x63
+
+#define ICH9_LPC_PIRQE_ROUT                     0x68
+#define ICH9_LPC_PIRQF_ROUT                     0x69
+#define ICH9_LPC_PIRQG_ROUT                     0x6a
+#define ICH9_LPC_PIRQH_ROUT                     0x6b
+
+#define  ICH9_LPC_PIRQ_ROUT_IRQEN               0x80
+#define  ICH9_LPC_PIRQ_ROUT_MASK                Q35_MASK(8, 3, 0)
+#define  ICH9_LPC_PIRQ_ROUT_DEFAULT             0x80
+
+#define ICH9_LPC_RCBA                           0xf0
+#define  ICH9_LPC_RCBA_BA_MASK                  Q35_MASK(32, 31, 14)
+#define  ICH9_LPC_RCBA_EN                       0x1
+#define  ICH9_LPC_RCBA_DEFAULT                  0x0
+
+/* D30:F1 power management I/O registers
+   offset from the address ICH9_LPC_PMBASE */
+
+/* ICH9 LPC PM I/O registers are 128 ports and 128-aligned */
+#define ICH9_PMIO_SIZE                          128
+#define ICH9_PMIO_MASK                          (ICH9_PMIO_SIZE - 1)
+
+#define ICH9_PMIO_PM1_STS                       0x00
+#define ICH9_PMIO_PM1_EN                        0x02
+#define ICH9_PMIO_PM1_CNT                       0x04
+#define ICH9_PMIO_PM1_TMR                       0x08
+#define ICH9_PMIO_GPE0_STS                      0x20
+#define ICH9_PMIO_GPE0_EN                       0x28
+#define ICH9_PMIO_SMI_EN                        0x30
+#define  ICH9_PMIO_SMI_EN_APMC_EN               (1 << 5)
+#define ICH9_PMIO_SMI_STS                       0x34
+
+/* FADT ACPI_ENABLE/ACPI_DISABLE */
+#define ICH9_APM_ACPI_ENABLE                    0x2
+#define ICH9_APM_ACPI_DISABLE                   0x3
+
+
+/* D30:F3 SMBus controller */
+#define ICH9_A2_SMB_REVISION                    0x02
+#define ICH9_SMB_PI                             0x00
+
+#define ICH9_SMB_SMBMBAR0                       0x10
+#define ICH9_SMB_SMBMBAR1                       0x14
+#define  ICH9_SMB_SMBM_BAR                      0
+#define  ICH9_SMB_SMBM_SIZE                     (1 << 8)
+#define ICH9_SMB_SMB_BASE                       0x20
+#define  ICH9_SMB_SMB_BASE_BAR                  4
+#define  ICH9_SMB_SMB_BASE_SIZE                 (1 << 5)
+#define ICH9_SMB_HOSTC                          0x40
+#define  ICH9_SMB_HOSTC_SSRESET                 ((uint8_t)(1 << 3))
+#define  ICH9_SMB_HOSTC_I2C_EN                  ((uint8_t)(1 << 2))
+#define  ICH9_SMB_HOSTC_SMB_SMI_EN              ((uint8_t)(1 << 1))
+#define  ICH9_SMB_HOSTC_HST_EN                  ((uint8_t)(1 << 0))
+
+/* D30:F3 SMBus I/O and memory mapped I/O registers */
+#define ICH9_SMB_HST_STS                        0x00
+#define ICH9_SMB_HST_CNT                        0x02
+#define ICH9_SMB_HST_CMD                        0x03
+#define ICH9_SMB_XMIT_SLVA                      0x04
+#define ICH9_SMB_HST_D0                         0x05
+#define ICH9_SMB_HST_D1                         0x06
+#define ICH9_SMB_HOST_BLOCK_DB                  0x07
+
+
+#endif /* HW_Q35_H */
diff --git a/hw/q35_smbus.c b/hw/q35_smbus.c
new file mode 100644
index 0000000..63ad8d3
--- /dev/null
+++ b/hw/q35_smbus.c
@@ -0,0 +1,150 @@
+/*
+ * ACPI implementation
+ *
+ * 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 Street, Fifth Floor, Boston MA  02110-1301 USA
+ */
+/*
+ *  Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ *                     VA Linux Systems Japan K.K.
+ *
+ *  This is based on acpi.c.
+ */
+#include "hw.h"
+#include "pc.h"
+#include "pc_smbus.h"
+#include "pci.h"
+#include "sysemu.h"
+#include "i2c.h"
+#include "smbus.h"
+
+#include "q35.h"
+
+typedef struct ICH9_SMBState {
+    PCIDevice dev;
+
+    PCSMBus smb;
+} ICH9_SMBState;
+
+static ICH9_SMBState *ich9_pci_to_smb(PCIDevice* pci_dev)
+{
+    return DO_UPCAST(ICH9_SMBState, dev, pci_dev);
+}
+
+static const VMStateDescription vmstate_ich9_smbus = {
+    .name = "ich9_smb",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_PCI_DEVICE(dev, struct ICH9_SMBState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void ich9_smb_reset(void *opaque)
+{
+    //ICH9_SMBState *s = opaque;
+    //uint8_t *pci_conf = s->dev.config;
+
+    /* XXX not yet */
+}
+
+static void ich9_smb_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+    ICH9_SMBState *s = opaque;
+    uint8_t hostc = s->dev.config[ICH9_SMB_HOSTC];
+
+    if (hostc & ICH9_SMB_HOSTC_HST_EN && !(hostc & ICH9_SMB_HOSTC_I2C_EN)) {
+        uint64_t offset = addr - s->dev.io_regions[ICH9_SMB_SMB_BASE_BAR].addr;
+        smb_ioport_writeb(&s->smb, offset, val);
+    }
+}
+
+static uint32_t ich9_smb_ioport_readb(void *opaque, uint32_t addr)
+{
+    ICH9_SMBState *s = opaque;
+    uint8_t hostc = s->dev.config[ICH9_SMB_HOSTC];
+
+    if (hostc & ICH9_SMB_HOSTC_HST_EN && !(hostc & ICH9_SMB_HOSTC_I2C_EN)) {
+        uint64_t offset = addr - s->dev.io_regions[ICH9_SMB_SMB_BASE_BAR].addr;
+        return smb_ioport_readb(&s->smb, offset);
+    }
+
+    return 0xff;
+}
+
+static void ich9_smb_map_ioport(PCIDevice *dev, int region_num,
+                                uint64_t addr, uint64_t size, int type)
+{
+    ICH9_SMBState *s = ich9_pci_to_smb(dev);
+
+    assert(size == ICH9_SMB_SMB_BASE_SIZE);
+    assert(type == PCI_ADDRESS_SPACE_IO);
+
+    register_ioport_write(addr, 64, 1, ich9_smb_ioport_writeb, s);
+    register_ioport_read(addr, 64, 1, ich9_smb_ioport_readb, s);
+}
+
+i2c_bus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base)
+{
+    ICH9_SMBState *s;
+    PCIDevice *d;
+
+    s = (ICH9_SMBState *)pci_register_device(bus,
+                                             "ICH9 SMB", sizeof(ICH9_SMBState),
+                                             devfn, NULL, NULL);
+    d = &s->dev;
+    pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_INTEL);
+    pci_config_set_device_id(d->config, PCI_DEVICE_ID_INTEL_ICH9_6);
+
+    pci_config_set_word(d, PCI_STATUS,
+                        PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM);
+    pci_conf_initw(d, PCI_STATUS,
+                   PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY);
+
+    pci_config_set_byte(d, PCI_REVISION_ID, ICH9_A2_SMB_REVISION);
+    pci_config_set_byte(d, PCI_CLASS_PROG, ICH9_SMB_PI);
+
+    pci_config_set_class(d->config, PCI_CLASS_SERIAL_SMBUS);
+    pci_config_set_byte(d, PCI_HEADER_TYPE, PCI_HEADER_TYPE_NORMAL); // header_type
+
+    /* XXX: D31IP.SMIP in chipset configuration space */
+    pci_config_set_byte(d, PCI_INTERRUPT_PIN, 0x01); // interrupt pin 1
+
+    pci_config_set_byte(d, ICH9_SMB_HOSTC, 0);
+
+
+    /* XXX:
+     * paralell_hds[0]
+     * serial_hds[0]
+     * serial_hds[0]
+     * fdc
+     */
+
+    // XXX smb_io_base
+    pci_config_set_byte(d, ICH9_SMB_HOSTC, 0);
+    /* XXX bar0, bar1: 64bit BAR support*/
+    pci_register_bar(d, ICH9_SMB_SMB_BASE_BAR,
+                     ICH9_SMB_SMB_BASE_SIZE, PCI_ADDRESS_SPACE_IO,
+                     &ich9_smb_map_ioport);
+
+    vmstate_register(0, &vmstate_ich9_smbus, s);
+
+    pc_smbus_init(&s->smb);
+    qemu_register_reset(ich9_smb_reset, s);
+
+    return s->smb.smbus;
+}
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 54/61] pci: add opaque argument to pci_map_irq_fn().
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (52 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 53/61] pc q35 based chipset emulator Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 55/61] ioapic: make ioapic_set_irq() static Isaku Yamahata
                   ` (10 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

To convert pci int pin to global irq or GSI, not only the pci device
which generates interrupt, but also the bus, like pci_set_irq_fn.
So pass the opaque argument to pci_map_irq_fn like pci_set_irq_fn.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c      |    8 +++++---
 hw/pci.h      |    5 +++--
 hw/piix_pci.c |    4 ++--
 hw/q35.c      |    4 ++--
 4 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 05cd2cb..600d9a1 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -155,6 +155,7 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
 }
 
 PCIBus *pci_register_secondary_bus(PCIDevice *dev, pci_map_irq_fn map_irq,
+                                   void *irq_opaque,
                                    const char* name, int devfn_min)
 {
     PCIBus *bus;
@@ -162,6 +163,7 @@ PCIBus *pci_register_secondary_bus(PCIDevice *dev, pci_map_irq_fn map_irq,
     bus = FROM_QBUS(PCIBus, qbus_create(&pci_bus_info, &dev->qdev, name));
 
     bus->map_irq = map_irq;
+    bus->irq_opaque = irq_opaque;
     bus->bus_num = dev->config[PCI_SECONDARY_BUS];
     bus->devfn_min = devfn_min;
 
@@ -1068,7 +1070,7 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
     pci_dev->irq_state[irq_num] = level;
     for (;;) {
         bus = pci_get_parent_bus(pci_dev);
-        irq_num = bus->map_irq(pci_dev, irq_num);
+        irq_num = bus->map_irq(bus->irq_opaque, pci_dev, irq_num);
         if (bus->set_irq)
             break;
         pci_dev = pci_bus_to_dev(bus);
@@ -1078,7 +1080,7 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
 }
 
 /* 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD */
-int pci_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin)
+int pci_swizzle_map_irq_fn(void *opauqe, PCIDevice *pci_dev, int pin)
 {
     return (pin + PCI_SLOT(pci_dev->devfn) - 1) % PCI_NUM_PINS;
 }
@@ -1524,7 +1526,7 @@ PCIBus *pci_bridge_create_simple(PCIBus *bus, int devfn, uint16_t vid,
     pci_config_set_byte(d, PCI_SECONDARY_BUS, sec_bus);
     pci_config_set_byte(d, PCI_SUBORDINATE_BUS, sub_bus);
 
-    return pci_register_secondary_bus(d, map_irq, bus_name, 0);
+    return pci_register_secondary_bus(d, map_irq, d, name, 0);
 }
 
 PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid,
diff --git a/hw/pci.h b/hw/pci.h
index 27a5d33..a1c37db 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -355,13 +355,14 @@ int pci_device_load(PCIDevice *s, QEMUFile *f);
 void pci_set_default_bus(PCIBus *bus);
 
 typedef void (*pci_set_irq_fn)(void *opaque, int irq_num, int level);
-typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num);
+typedef int (*pci_map_irq_fn)(void *opaque, PCIDevice *pci_dev, int irq_num);
 /* 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD */
-int pci_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin);
+int pci_swizzle_map_irq_fn(void *opaque, PCIDevice *pci_dev, int pin);
 PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
                          void *irq_opaque, int devfn_min, int nirq);
 PCIBus *pci_register_secondary_bus(PCIDevice *dev, pci_map_irq_fn map_irq,
+                                   void *irq_opaque,
                                    const char* name, int devfn_min);
 
 PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index 87cdbd9..a422d52 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -67,9 +67,9 @@ static void piix3_set_irq(void *opaque, int irq_num, int level);
 /* return the global irq number corresponding to a given device irq
    pin. We could also use the bus number to have a more precise
    mapping. */
-static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
+static int pci_slot_get_pirq(void *opaque, PCIDevice *pci_dev, int irq_num)
 {
-    return pci_swizzle_map_irq_fn(pci_dev, irq_num);
+    return pci_swizzle_map_irq_fn(NULL, pci_dev, irq_num);
 }
 
 static void update_pam(PCII440FXState *d, uint32_t start, uint32_t end, int r)
diff --git a/hw/q35.c b/hw/q35.c
index 8e07048..05267ea 100644
--- a/hw/q35.c
+++ b/hw/q35.c
@@ -157,9 +157,9 @@ static void ich9_lpc_set_irq(void *opaque, int irq_num, int level);
 /* return the global irq number corresponding to a given device irq
    pin. We could also use the bus number to have a more precise
    mapping. */
-static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
+static int pci_slot_get_pirq(void *opaque, PCIDevice *pci_dev, int irq_num)
 {
-    return pci_swizzle_map_irq_fn(pci_dev, irq_num);
+    return pci_swizzle_map_irq_fn(NULL, pci_dev, irq_num);
 }
 
 /* PAM */
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 55/61] ioapic: make ioapic_set_irq() static.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (53 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 54/61] pci: add opaque argument to pci_map_irq_fn() Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 56/61] ioapic: clean up of #ifdef DEBUG_IOAPIC Isaku Yamahata
                   ` (9 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

ioapic_set_irq() is used locally.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/ioapic.c |    2 +-
 hw/pc.h     |    1 -
 2 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/hw/ioapic.c b/hw/ioapic.c
index b0ad78f..e97e258 100644
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@ -86,7 +86,7 @@ static void ioapic_service(IOAPICState *s)
     }
 }
 
-void ioapic_set_irq(void *opaque, int vector, int level)
+static void ioapic_set_irq(void *opaque, int vector, int level)
 {
     IOAPICState *s = opaque;
 
diff --git a/hw/pc.h b/hw/pc.h
index cf34db6..7577956 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -52,7 +52,6 @@ int apic_accept_pic_intr(CPUState *env);
 void apic_deliver_pic_intr(CPUState *env, int level);
 int apic_get_interrupt(CPUState *env);
 qemu_irq *ioapic_init(void);
-void ioapic_set_irq(void *opaque, int vector, int level);
 void apic_reset_irq_delivered(void);
 int apic_get_irq_delivered(void);
 
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 56/61] ioapic: clean up of #ifdef DEBUG_IOAPIC.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (54 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 55/61] ioapic: make ioapic_set_irq() static Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 57/61] ioapic: add callback when entry is set or ioapic is reset Isaku Yamahata
                   ` (8 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

remove unnecessary #ifdef DEBUG_IOAPIC.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/ioapic.c |   13 +++++++------
 1 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/hw/ioapic.c b/hw/ioapic.c
index e97e258..a9a8e00 100644
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@ -26,6 +26,11 @@
 #include "host-utils.h"
 
 //#define DEBUG_IOAPIC
+#ifdef DEBUG_IOAPIC
+# define IOAPIC_DPRINTF(format, ...)    printf(format, ## __VA_ARGS__)
+#else
+# define IOAPIC_DPRINTF(format, ...)    do { } while (0)
+#endif
 
 #define IOAPIC_NUM_PINS			0x18
 #define IOAPIC_LVT_MASKED 		(1<<16)
@@ -148,9 +153,7 @@ static uint32_t ioapic_mem_readl(void *opaque, target_phys_addr_t addr)
                         val = s->ioredtbl[index] & 0xffffffff;
                 }
         }
-#ifdef DEBUG_IOAPIC
-        printf("I/O APIC read: %08x = %08x\n", s->ioregsel, val);
-#endif
+        IOAPIC_DPRINTF("I/O APIC read: %08x = %08x\n", s->ioregsel, val);
     }
     return val;
 }
@@ -165,9 +168,7 @@ static void ioapic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t va
         s->ioregsel = val;
         return;
     } else if (addr == 0x10) {
-#ifdef DEBUG_IOAPIC
-        printf("I/O APIC write: %08x = %08x\n", s->ioregsel, val);
-#endif
+        IOAPIC_DPRINTF("I/O APIC write: %08x = %08x\n", s->ioregsel, val);
         switch (s->ioregsel) {
             case 0x00:
                 s->id = (val >> 24) & 0xff;
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 57/61] ioapic: add callback when entry is set or ioapic is reset
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (55 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 56/61] ioapic: clean up of #ifdef DEBUG_IOAPIC Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-10-01 13:37   ` Gleb Natapov
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 58/61] ioapic: make the number of pins configurable Isaku Yamahata
                   ` (7 subsequent siblings)
  64 siblings, 1 reply; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

Add hooks to ioapic.
This is necessary for pci interrupt routing mode from
PIC mode to IO APIC mode.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/ioapic.c |   20 +++++++++++++++++++-
 hw/pc.h     |    2 ++
 2 files changed, 21 insertions(+), 1 deletions(-)

diff --git a/hw/ioapic.c b/hw/ioapic.c
index a9a8e00..882ca9d 100644
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@ -53,8 +53,16 @@ struct IOAPICState {
 
     uint32_t irr;
     uint64_t ioredtbl[IOAPIC_NUM_PINS];
+    ioapic_update_fn update_fn;
+    void *opaque;
 };
 
+static void ioapic_callback(IOAPICState *s, int reset)
+{
+    if (s->update_fn)
+        s->update_fn(s->opaque, reset);
+}
+
 static void ioapic_service(IOAPICState *s)
 {
     uint8_t i;
@@ -186,6 +194,7 @@ static void ioapic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t va
                         s->ioredtbl[index] &= ~0xffffffffULL;
                         s->ioredtbl[index] |= val;
                     }
+                    ioapic_callback(s, 0);
                     ioapic_service(s);
                 }
         }
@@ -210,6 +219,8 @@ static void ioapic_reset(void *opaque)
     IOAPICState *s = opaque;
     int i;
 
+    ioapic_callback(s, 1);
+
     memset(s, 0, sizeof(*s));
     for(i = 0; i < IOAPIC_NUM_PINS; i++)
         s->ioredtbl[i] = 1 << 16; /* mask LVT */
@@ -227,13 +238,15 @@ static CPUWriteMemoryFunc * const ioapic_mem_write[3] = {
     ioapic_mem_writel,
 };
 
-qemu_irq *ioapic_init(void)
+qemu_irq *ioapic_init_with_arg(ioapic_update_fn update_fn, void *opaque)
 {
     IOAPICState *s;
     qemu_irq *irq;
     int io_memory;
 
     s = qemu_mallocz(sizeof(IOAPICState));
+    s->update_fn = update_fn;
+    s->opaque = opaque;
     ioapic_reset(s);
 
     io_memory = cpu_register_io_memory(ioapic_mem_read,
@@ -246,3 +259,8 @@ qemu_irq *ioapic_init(void)
 
     return irq;
 }
+
+qemu_irq *ioapic_init(void)
+{
+    return ioapic_init_with_arg(NULL, NULL);
+}
diff --git a/hw/pc.h b/hw/pc.h
index 7577956..44eac49 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -52,6 +52,8 @@ int apic_accept_pic_intr(CPUState *env);
 void apic_deliver_pic_intr(CPUState *env, int level);
 int apic_get_interrupt(CPUState *env);
 qemu_irq *ioapic_init(void);
+typedef void (*ioapic_update_fn)(void *opaque, int reset);
+qemu_irq *ioapic_init_with_arg(ioapic_update_fn update_fn, void *opaque);
 void apic_reset_irq_delivered(void);
 int apic_get_irq_delivered(void);
 
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 58/61] ioapic: make the number of pins configurable.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (56 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 57/61] ioapic: add callback when entry is set or ioapic is reset Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 59/61] ioapic: make irr accept more than 32 pins Isaku Yamahata
                   ` (6 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

make the number of pins configurable.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/hw.h     |   20 +++++++++++++++++
 hw/ioapic.c |   66 ++++++++++++++++++++++++++++++++++++++++++++--------------
 hw/pc.h     |    3 +-
 3 files changed, 72 insertions(+), 17 deletions(-)

diff --git a/hw/hw.h b/hw/hw.h
index 19e9199..6f78285 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -365,6 +365,17 @@ extern const VMStateInfo vmstate_info_buffer;
         + type_check_array(_type,typeof_field(_state, _field),_num)  \
 }
 
+#define VMSTATE_ARRAY_POINTER(_field, _state, _num, _version, _info, _type) {\
+    .name       = (stringify(_field)),                               \
+    .version_id = (_version),                                        \
+    .num        = (_num),                                            \
+    .info       = &(_info),                                          \
+    .size       = sizeof(_type),                                     \
+    .flags      = VMS_ARRAY|VMS_POINTER,                             \
+    .offset     = offsetof(_state, _field)                           \
+        + type_check_pointer(_type,typeof_field(_state, _field))     \
+}
+
 #define VMSTATE_VARRAY(_field, _state, _field_num, _version, _info, _type) {\
     .name       = (stringify(_field)),                               \
     .version_id = (_version),                                        \
@@ -532,6 +543,15 @@ extern const VMStateDescription vmstate_pcie_device;
 #define VMSTATE_UINT64_ARRAY(_f, _s, _n)                              \
     VMSTATE_UINT64_ARRAY_V(_f, _s, _n, 0)
 
+#define VMSTATE_UINT64_ARRAY_POINTER(_f, _s, _n)                      \
+    VMSTATE_ARRAY_POINTER(_f, _s, _n, 0, vmstate_info_uint64, uint64_t)
+
+#define VMSTATE_UINT64_VARRAY_V(_f, _s, _f_n, _v)                     \
+    VMSTATE_VARRAY(_f, _s, _f_n, _v, vmstate_info_uint64, uint64_t)
+
+#define VMSTATE_UINT64_VARRAY(_f, _s, _f_n)                           \
+    VMSTATE_UINT64_VARRAY_V(_f, _s, _f_n, 0)
+
 #define VMSTATE_INT32_ARRAY_V(_f, _s, _n, _v)                         \
     VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_int32, int32_t)
 
diff --git a/hw/ioapic.c b/hw/ioapic.c
index 882ca9d..adaef41 100644
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@ -32,7 +32,7 @@
 # define IOAPIC_DPRINTF(format, ...)    do { } while (0)
 #endif
 
-#define IOAPIC_NUM_PINS			0x18
+#define IOAPIC_NUM_PINS_DEFAULT		0x18
 #define IOAPIC_LVT_MASKED 		(1<<16)
 
 #define IOAPIC_TRIGGER_EDGE		0
@@ -48,11 +48,12 @@
 #define IOAPIC_DM_EXTINT		0x7
 
 struct IOAPICState {
+    int32_t num_pins;   /* MRE: maximum redirection entries */
     uint8_t id;
     uint8_t ioregsel;
 
     uint32_t irr;
-    uint64_t ioredtbl[IOAPIC_NUM_PINS];
+    uint64_t *ioredtbl;
     ioapic_update_fn update_fn;
     void *opaque;
 };
@@ -75,7 +76,7 @@ static void ioapic_service(IOAPICState *s)
     uint8_t dest_mode;
     uint8_t polarity;
 
-    for (i = 0; i < IOAPIC_NUM_PINS; i++) {
+    for (i = 0; i < s->num_pins; i++) {
         mask = 1 << i;
         if (s->irr & mask) {
             entry = s->ioredtbl[i];
@@ -110,7 +111,7 @@ static void ioapic_set_irq(void *opaque, int vector, int level)
     if (vector == 0)
         vector = 2;
 
-    if (vector >= 0 && vector < IOAPIC_NUM_PINS) {
+    if (vector >= 0 && vector < s->num_pins) {
         uint32_t mask = 1 << vector;
         uint64_t entry = s->ioredtbl[vector];
 
@@ -147,14 +148,14 @@ static uint32_t ioapic_mem_readl(void *opaque, target_phys_addr_t addr)
                 val = s->id << 24;
                 break;
             case 0x01:
-                val = 0x11 | ((IOAPIC_NUM_PINS - 1) << 16); /* version 0x11 */
+                val = 0x11 | ((s->num_pins - 1) << 16); /* version 0x11 */
                 break;
             case 0x02:
                 val = 0;
                 break;
             default:
                 index = (s->ioregsel - 0x10) >> 1;
-                if (index >= 0 && index < IOAPIC_NUM_PINS) {
+                if (index >= 0 && index < s->num_pins) {
                     if (s->ioregsel & 1)
                         val = s->ioredtbl[index] >> 32;
                     else
@@ -186,7 +187,7 @@ static void ioapic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t va
                 return;
             default:
                 index = (s->ioregsel - 0x10) >> 1;
-                if (index >= 0 && index < IOAPIC_NUM_PINS) {
+                if (index >= 0 && index < s->num_pins) {
                     if (s->ioregsel & 1) {
                         s->ioredtbl[index] &= 0xffffffff;
                         s->ioredtbl[index] |= (uint64_t)val << 32;
@@ -209,7 +210,22 @@ static const VMStateDescription vmstate_ioapic = {
     .fields      = (VMStateField []) {
         VMSTATE_UINT8(id, IOAPICState),
         VMSTATE_UINT8(ioregsel, IOAPICState),
-        VMSTATE_UINT64_ARRAY(ioredtbl, IOAPICState, IOAPIC_NUM_PINS),
+        VMSTATE_UINT64_ARRAY_POINTER(ioredtbl, IOAPICState,
+                                     IOAPIC_NUM_PINS_DEFAULT),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_ioapic_with_mre = {
+    .name = "ioapic",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField []) {
+        VMSTATE_INT32(num_pins, IOAPICState),
+        VMSTATE_UINT8(id, IOAPICState),
+        VMSTATE_UINT8(ioregsel, IOAPICState),
+        VMSTATE_UINT64_VARRAY(ioredtbl, IOAPICState, num_pins),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -221,8 +237,10 @@ static void ioapic_reset(void *opaque)
 
     ioapic_callback(s, 1);
 
-    memset(s, 0, sizeof(*s));
-    for(i = 0; i < IOAPIC_NUM_PINS; i++)
+    s->id = 0;
+    s->ioregsel = 0;
+    s->irr = 0;
+    for(i = 0; i < s->num_pins; i++)
         s->ioredtbl[i] = 1 << 16; /* mask LVT */
 }
 
@@ -238,13 +256,18 @@ static CPUWriteMemoryFunc * const ioapic_mem_write[3] = {
     ioapic_mem_writel,
 };
 
-qemu_irq *ioapic_init_with_arg(ioapic_update_fn update_fn, void *opaque)
+static void ioapic_init_with_arg(uint8_t num_pins,
+                                 ioapic_update_fn update_fn, void *opaque,
+                                 IOAPICState **sp, qemu_irq **irq)
 {
     IOAPICState *s;
-    qemu_irq *irq;
     int io_memory;
 
-    s = qemu_mallocz(sizeof(IOAPICState));
+    s = qemu_mallocz(sizeof(*s));
+    *sp = s;
+
+    s->ioredtbl = qemu_mallocz(sizeof(s->ioredtbl[0]) * num_pins);
+    s->num_pins = num_pins;
     s->update_fn = update_fn;
     s->opaque = opaque;
     ioapic_reset(s);
@@ -253,14 +276,25 @@ qemu_irq *ioapic_init_with_arg(ioapic_update_fn update_fn, void *opaque)
                                        ioapic_mem_write, s);
     cpu_register_physical_memory(0xfec00000, 0x1000, io_memory);
 
-    vmstate_register(0, &vmstate_ioapic, s);
     qemu_register_reset(ioapic_reset, s);
-    irq = qemu_allocate_irqs(ioapic_set_irq, s, IOAPIC_NUM_PINS);
+    *irq = qemu_allocate_irqs(ioapic_set_irq, s, num_pins);
+}
 
+qemu_irq *ioapic_init_with_mre(uint8_t num_pins,
+                               ioapic_update_fn update_fn, void *opaque)
+{
+    IOAPICState *s;
+    qemu_irq *irq;
+    ioapic_init_with_arg(num_pins, update_fn, opaque, &s, &irq);
+    vmstate_register(0, &vmstate_ioapic_with_mre, s);
     return irq;
 }
 
 qemu_irq *ioapic_init(void)
 {
-    return ioapic_init_with_arg(NULL, NULL);
+    IOAPICState *s;
+    qemu_irq *irq;
+    ioapic_init_with_arg(IOAPIC_NUM_PINS_DEFAULT, NULL, NULL, &s, &irq);
+    vmstate_register(0, &vmstate_ioapic, s);
+    return irq;
 }
diff --git a/hw/pc.h b/hw/pc.h
index 44eac49..723c478 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -53,7 +53,8 @@ void apic_deliver_pic_intr(CPUState *env, int level);
 int apic_get_interrupt(CPUState *env);
 qemu_irq *ioapic_init(void);
 typedef void (*ioapic_update_fn)(void *opaque, int reset);
-qemu_irq *ioapic_init_with_arg(ioapic_update_fn update_fn, void *opaque);
+qemu_irq *ioapic_init_with_mre(uint8_t num_pins,
+                               ioapic_update_fn update_fn, void *opaque);
 void apic_reset_irq_delivered(void);
 int apic_get_irq_delivered(void);
 
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 59/61] ioapic: make irr accept more than 32 pins.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (57 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 58/61] ioapic: make the number of pins configurable Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-10-01  8:52   ` Avi Kivity
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 60/61] pci: add opaque arg to pci_map_irq_fn Isaku Yamahata
                   ` (5 subsequent siblings)
  64 siblings, 1 reply; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

make irr accept more than 32 pins.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/ioapic.c |   44 +++++++++++++++++++++++++++++++++-----------
 1 files changed, 33 insertions(+), 11 deletions(-)

diff --git a/hw/ioapic.c b/hw/ioapic.c
index adaef41..2082c4d 100644
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@ -33,6 +33,8 @@
 #endif
 
 #define IOAPIC_NUM_PINS_DEFAULT		0x18
+#define IOAPIC_NUM_PINS_MIN		16
+#define IOAPIC_NUM_PINS_MAX		240
 #define IOAPIC_LVT_MASKED 		(1<<16)
 
 #define IOAPIC_TRIGGER_EDGE		0
@@ -52,7 +54,7 @@ struct IOAPICState {
     uint8_t id;
     uint8_t ioregsel;
 
-    uint32_t irr;
+    uint8_t *irr;
     uint64_t *ioredtbl;
     ioapic_update_fn update_fn;
     void *opaque;
@@ -64,21 +66,39 @@ static void ioapic_callback(IOAPICState *s, int reset)
         s->update_fn(s->opaque, reset);
 }
 
+static int ioapic_irr_is_set(IOAPICState *s, int vector)
+{
+    return (s->irr[vector / 8] & (1 << (vector % 8)));
+}
+
+static void ioapic_irr_set(IOAPICState *s, int vector)
+{
+    s->irr[vector / 8] |= (1 << (vector % 8));
+}
+
+static void ioapic_irr_clear(IOAPICState *s, int vector)
+{
+    s->irr[vector / 8] &= ~(1 << (vector % 8));
+}
+
+static size_t ioapic_irr_size(int num_pins)
+{
+    return (num_pins + 7) / 8 * sizeof(uint8_t);
+}
+
 static void ioapic_service(IOAPICState *s)
 {
     uint8_t i;
     uint8_t trig_mode;
     uint8_t vector;
     uint8_t delivery_mode;
-    uint32_t mask;
     uint64_t entry;
     uint8_t dest;
     uint8_t dest_mode;
     uint8_t polarity;
 
     for (i = 0; i < s->num_pins; i++) {
-        mask = 1 << i;
-        if (s->irr & mask) {
+        if (ioapic_irr_is_set(s, i)) {
             entry = s->ioredtbl[i];
             if (!(entry & IOAPIC_LVT_MASKED)) {
                 trig_mode = ((entry >> 15) & 1);
@@ -87,7 +107,7 @@ static void ioapic_service(IOAPICState *s)
                 delivery_mode = (entry >> 8) & 7;
                 polarity = (entry >> 13) & 1;
                 if (trig_mode == IOAPIC_TRIGGER_EDGE)
-                    s->irr &= ~mask;
+                    ioapic_irr_clear(s, i);
                 if (delivery_mode == IOAPIC_DM_EXTINT)
                     vector = pic_read_irq(isa_pic);
                 else
@@ -112,21 +132,20 @@ static void ioapic_set_irq(void *opaque, int vector, int level)
         vector = 2;
 
     if (vector >= 0 && vector < s->num_pins) {
-        uint32_t mask = 1 << vector;
         uint64_t entry = s->ioredtbl[vector];
 
         if ((entry >> 15) & 1) {
             /* level triggered */
             if (level) {
-                s->irr |= mask;
+                ioapic_irr_set(s, vector);
                 ioapic_service(s);
             } else {
-                s->irr &= ~mask;
+                ioapic_irr_clear(s, vector);
             }
         } else {
             /* edge triggered */
             if (level) {
-                s->irr |= mask;
+                ioapic_irr_set(s, vector);
                 ioapic_service(s);
             }
         }
@@ -239,7 +258,7 @@ static void ioapic_reset(void *opaque)
 
     s->id = 0;
     s->ioregsel = 0;
-    s->irr = 0;
+    memset(s->irr, 0, ioapic_irr_size(s->num_pins));
     for(i = 0; i < s->num_pins; i++)
         s->ioredtbl[i] = 1 << 16; /* mask LVT */
 }
@@ -263,11 +282,14 @@ static void ioapic_init_with_arg(uint8_t num_pins,
     IOAPICState *s;
     int io_memory;
 
+    assert(IOAPIC_NUM_PINS_MIN <= num_pins);
+    assert(num_pins <= IOAPIC_NUM_PINS_MAX);
     s = qemu_mallocz(sizeof(*s));
     *sp = s;
 
-    s->ioredtbl = qemu_mallocz(sizeof(s->ioredtbl[0]) * num_pins);
     s->num_pins = num_pins;
+    s->irr = qemu_mallocz(ioapic_irr_size(num_pins));
+    s->ioredtbl = qemu_mallocz(sizeof(s->ioredtbl[0]) * num_pins);
     s->update_fn = update_fn;
     s->opaque = opaque;
     ioapic_reset(s);
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 60/61] pci: add opaque arg to pci_map_irq_fn.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (58 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 59/61] ioapic: make irr accept more than 32 pins Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 61/61] pc_q35: apic mode for pci interrupt routing Isaku Yamahata
                   ` (4 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

add opaque arg to pci_map_irq_fn.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/apb_pci.c       |    4 ++--
 hw/grackle_pci.c   |    2 +-
 hw/gt64xxx.c       |    2 +-
 hw/ppc4xx_pci.c    |    2 +-
 hw/ppce500_pci.c   |    2 +-
 hw/prep_pci.c      |    2 +-
 hw/r2d.c           |    2 +-
 hw/unin_pci.c      |    2 +-
 hw/versatile_pci.c |    2 +-
 9 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index f679847..17d63c6 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -203,12 +203,12 @@ static CPUReadMemoryFunc * const pci_apb_ioread[] = {
 };
 
 /* The APB host has an IRQ line for each IRQ line of each slot.  */
-static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
+static int pci_apb_map_irq(void *opaque, PCIDevice *pci_dev, int irq_num)
 {
     return ((pci_dev->devfn & 0x18) >> 1) + irq_num;
 }
 
-static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
+static int pci_pbm_map_irq(void *opaque, PCIDevice *pci_dev, int irq_num)
 {
     int bus_offset;
     if (pci_dev->devfn & 1)
diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
index 59664b7..2a5bdd3 100644
--- a/hw/grackle_pci.c
+++ b/hw/grackle_pci.c
@@ -97,7 +97,7 @@ static CPUReadMemoryFunc * const pci_grackle_read[] = {
 };
 
 /* Don't know if this matches real hardware, but it agrees with OHW.  */
-static int pci_grackle_map_irq(PCIDevice *pci_dev, int irq_num)
+static int pci_grackle_map_irq(void *opaque, PCIDevice *pci_dev, int irq_num)
 {
     return (irq_num + (pci_dev->devfn >> 3)) & 3;
 }
diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c
index f8d0dcc..a85190a 100644
--- a/hw/gt64xxx.c
+++ b/hw/gt64xxx.c
@@ -866,7 +866,7 @@ static CPUReadMemoryFunc * const gt64120_read[] = {
     &gt64120_readl,
 };
 
-static int pci_gt64120_map_irq(PCIDevice *pci_dev, int irq_num)
+static int pci_gt64120_map_irq(void *opaque, PCIDevice *pci_dev, int irq_num)
 {
     int slot;
 
diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
index 01b8eb1..5170976 100644
--- a/hw/ppc4xx_pci.c
+++ b/hw/ppc4xx_pci.c
@@ -294,7 +294,7 @@ static void ppc4xx_pci_reset(void *opaque)
 
 /* On Bamboo, all pins from each slot are tied to a single board IRQ. This
  * may need further refactoring for other boards. */
-static int ppc4xx_pci_map_irq(PCIDevice *pci_dev, int irq_num)
+static int ppc4xx_pci_map_irq(void *opaque, PCIDevice *pci_dev, int irq_num)
 {
     int slot = pci_dev->devfn >> 3;
 
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index e388a9a..727f096 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -233,7 +233,7 @@ static CPUWriteMemoryFunc * const e500_pci_reg_write[] = {
     &pci_reg_write4,
 };
 
-static int mpc85xx_pci_map_irq(PCIDevice *pci_dev, int irq_num)
+static int mpc85xx_pci_map_irq(void *opaque, PCIDevice *pci_dev, int irq_num)
 {
     int devno = pci_dev->devfn >> 3, ret = 0;
 
diff --git a/hw/prep_pci.c b/hw/prep_pci.c
index 72498bf..5113550 100644
--- a/hw/prep_pci.c
+++ b/hw/prep_pci.c
@@ -119,7 +119,7 @@ static CPUReadMemoryFunc * const PPC_PCIIO_read[] = {
     &PPC_PCIIO_readl,
 };
 
-static int prep_map_irq(PCIDevice *pci_dev, int irq_num)
+static int prep_map_irq(void *opaque, PCIDevice *pci_dev, int irq_num)
 {
     return (irq_num + (pci_dev->devfn >> 3)) & 1;
 }
diff --git a/hw/r2d.c b/hw/r2d.c
index ea19ff6..59dbc43 100644
--- a/hw/r2d.c
+++ b/hw/r2d.c
@@ -191,7 +191,7 @@ static void r2d_pci_set_irq(void *opaque, int n, int l)
     qemu_set_irq(p[n], l);
 }
 
-static int r2d_pci_map_irq(PCIDevice *d, int irq_num)
+static int r2d_pci_map_irq(void *opaque, PCIDevice *d, int irq_num)
 {
     const int intx[] = { PCI_INTA, PCI_INTB, PCI_INTC, PCI_INTD };
     return intx[d->devfn >> 3];
diff --git a/hw/unin_pci.c b/hw/unin_pci.c
index ac69b7f..8fc0b6a 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -136,7 +136,7 @@ static CPUReadMemoryFunc * const pci_unin_read[] = {
 };
 
 /* Don't know if this matches real hardware, but it agrees with OHW.  */
-static int pci_unin_map_irq(PCIDevice *pci_dev, int irq_num)
+static int pci_unin_map_irq(void *opaque, PCIDevice *pci_dev, int irq_num)
 {
     return (irq_num + (pci_dev->devfn >> 3)) & 3;
 }
diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c
index a0d7d07..5770635 100644
--- a/hw/versatile_pci.c
+++ b/hw/versatile_pci.c
@@ -85,7 +85,7 @@ static CPUReadMemoryFunc * const pci_vpb_config_read[] = {
     &pci_vpb_config_readl,
 };
 
-static int pci_vpb_map_irq(PCIDevice *d, int irq_num)
+static int pci_vpb_map_irq(void *opaque, PCIDevice *d, int irq_num)
 {
     return irq_num;
 }
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] [PATCH 61/61] pc_q35: apic mode for pci interrupt routing.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (59 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 60/61] pci: add opaque arg to pci_map_irq_fn Isaku Yamahata
@ 2009-09-30 10:18 ` Isaku Yamahata
  2009-10-01  8:50   ` Avi Kivity
  2009-09-30 12:00 ` [Qemu-devel] Re: [PATCH 00/61] Q35 chip set and stuff Michael S. Tsirkin
                   ` (3 subsequent siblings)
  64 siblings, 1 reply; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 10:18 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

apic mode for pci interrupt routing.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pc_q35.c |    4 +-
 hw/q35.c    |   87 +++++++++++++++++++++++++++++++++++++++++++++++-----------
 hw/q35.h    |    6 +++-
 3 files changed, 77 insertions(+), 20 deletions(-)

diff --git a/hw/pc_q35.c b/hw/pc_q35.c
index 9980a39..105b97b 100644
--- a/hw/pc_q35.c
+++ b/hw/pc_q35.c
@@ -132,10 +132,10 @@ static void pc_q35_init(ram_addr_t ram_size,
     i8259 = i8259_init(cpu_irq[0]);
     isa_irq_state = qemu_mallocz(sizeof(*isa_irq_state));
     isa_irq_state->i8259 = i8259;
-    isa_irq_state->ioapic = ioapic_init();
     isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24);
 
-    host_bus = gmch_init(&gmch_state, isa_irq, &ich9_lpc_devfn);
+    host_bus = gmch_init(&gmch_state, isa_irq, &ich9_lpc_devfn,
+                         &isa_irq_state->ioapic);
 
     isa_bus_irqs(isa_irq);
     pc_register_ferr_irq(isa_reserve_irq(13));
diff --git a/hw/q35.c b/hw/q35.c
index 05267ea..06dbdf9 100644
--- a/hw/q35.c
+++ b/hw/q35.c
@@ -59,6 +59,7 @@ struct ICH9_LPCState {
     /* ICH9 LPC PCI to ISA bridge */
     PCIDevice d;
 
+    int apic_mode;
     int pci_irq_levels[ICH9_LPC_NB_PIRQS];
 
     APMState apm;
@@ -68,6 +69,7 @@ struct ICH9_LPCState {
 struct ICH9_LPCIrqState {
     struct ICH9_LPCState *lpc;
     qemu_irq *pic;
+    qemu_irq *ioapic;
 };
 
 typedef struct GMCHState {
@@ -154,12 +156,42 @@ static void gmch_update_pcixbar(struct GMCH_PCIState *gs)
 static struct ICH9_LPCState *ich9_lpc_init(PCIBus *bus, int devfn, struct ICH9_LPCIrqState *irq_state);
 static void ich9_lpc_set_irq(void *opaque, int irq_num, int level);
 
+static void ich9_lpc_ioapic_update_fn(void *opaque, int reset)
+{
+    struct ICH9_LPCIrqState *irq_state = opaque;
+    struct ICH9_LPCState *ich9_lpc = irq_state->lpc;
+
+    /* this can be called via gmch_init() where ich9_lpc isn't
+       allocated yet */
+    if (ich9_lpc == NULL)
+        return;
+
+    if (reset)
+        ich9_lpc->apic_mode = 0;
+    else
+        ich9_lpc->apic_mode = 1;
+}
+
 /* return the global irq number corresponding to a given device irq
-   pin. We could also use the bus number to have a more precise
-   mapping. */
-static int pci_slot_get_pirq(void *opaque, PCIDevice *pci_dev, int irq_num)
+   pin.
+   pic mode: LNKx
+   apic mode: gsi
+   We could also use the bus number/device to have a more precise mapping. */
+static int pci_slot_map_irq(void *opaque, PCIDevice *pci_dev, int irq_num)
 {
-    return pci_swizzle_map_irq_fn(NULL, pci_dev, irq_num);
+    struct ICH9_LPCIrqState *irq_state = opaque;
+    struct ICH9_LPCState *lpc = irq_state->lpc;
+    int pin = pci_swizzle_map_irq_fn(NULL, pci_dev, irq_num);
+
+    if (!lpc->apic_mode) {
+        /* INTA -> INKA, ...
+           this would be device wise... */
+        return pin;
+    }
+
+    /* APIC mode INTA -> 16, ...
+       this would be device wise... */
+    return pin + ICH9_LPC_PIC_NUM_PINS;
 }
 
 /* PAM */
@@ -385,24 +417,30 @@ static int gmch_initfn(PCIDevice *d)
 }
 
 /* host bridge */
-PCIBus *gmch_init(PCIDevice **pgmch_state, qemu_irq *pic, int *ich9_lpc_devfn)
+PCIBus *gmch_init(PCIDevice **pgmch_state, qemu_irq *pic, int *ich9_lpc_devfn,
+                  qemu_irq **ioapic)
 {
     DeviceState *dev;
     GMCHState *s;
     PCIBus *b;
     PCIDevice *d;
     struct GMCH_PCIState *gs;
-    struct ICH9_LPCIrqState *irq_state = qemu_malloc(sizeof(*irq_state));
+    struct ICH9_LPCIrqState *irq_state = qemu_mallocz(sizeof(*irq_state));
 
     irq_state->pic = pic;
     dev = qdev_create(NULL, "gmch-pcihost");
     s = gmchstate_from_sysbus(sysbus_from_qdev(dev));
     b = pci_register_bus(dev, "pci.0",
-                         ich9_lpc_set_irq, pci_slot_get_pirq, irq_state, 0,
+                         ich9_lpc_set_irq, pci_slot_map_irq, irq_state, 0,
                          24 /* 24 pin IO APIC */);
     s->host.pci.bus = b;
     qdev_init(dev);
 
+    *ioapic = ioapic_init_with_mre(ICH9_LPC_IOAPIC_NUM_PINS,
+                                   ich9_lpc_ioapic_update_fn,
+                                   irq_state);
+    irq_state->ioapic = *ioapic;
+
     d = pci_create_simple(b, 0, "gmch");
     s->dev = d;
     gs = DO_UPCAST(struct GMCH_PCIState, d, d);
@@ -554,11 +592,10 @@ static void ich9_lpc_pic_irq(struct ICH9_LPCState *lpc, int irq_num,
     abort();
 }
 
-static void ich9_lpc_set_irq(void *opaque, int irq_num, int level)
+/* irq_num = LNKx: 0 = LNKA, ... */
+static void ich9_lpc_set_irq_pic(struct ICH9_LPCState *ich9_lpc,
+                                 qemu_irq *pic, int irq_num, int level)
 {
-    struct ICH9_LPCIrqState *irq_state = opaque;
-    struct ICH9_LPCState *ich9_lpc = irq_state->lpc;
-    qemu_irq *pic = irq_state->pic;
     int i, pic_level;
     int pic_irq;
     int pic_dis;
@@ -569,16 +606,11 @@ static void ich9_lpc_set_irq(void *opaque, int irq_num, int level)
     /* now we change the pic irq level according to
        the ich9 lpc irq mappings */
     ich9_lpc_pic_irq(ich9_lpc, irq_num, &pic_irq, &pic_dis);
+    assert(pic_irq < ICH9_LPC_PIC_NUM_PINS);
     if (pic_dis) {
         return;
     }
 
-    if (pic_irq > 24) {
-        fprintf(stderr, "%s: error irq_num %d pic_irq %d\n",
-                __func__, irq_num, pic_irq);
-        return;
-    }
-
     /* The pic level is the logical OR of all the PCI irqs mapped to it */
     pic_level = 0;
     for (i = 0; i < ICH9_LPC_NB_PIRQS; i++) {
@@ -592,6 +624,27 @@ static void ich9_lpc_set_irq(void *opaque, int irq_num, int level)
     qemu_set_irq(pic[pic_irq], pic_level);
 }
 
+/* irq_num = GSI */
+static void ich9_lpc_set_irq_apic(struct ICH9_LPCState *ich9_lpc,
+                                  qemu_irq *ioapic, int irq_num, int level)
+{
+    assert(irq_num < ICH9_LPC_IOAPIC_NUM_PINS);
+    qemu_set_irq(ioapic[irq_num], level);
+}
+
+/* pic mode:  irq_num = LNKx
+   apic mode: irq_num = GSI */
+static void ich9_lpc_set_irq(void *opaque, int irq_num, int level)
+{
+    struct ICH9_LPCIrqState *irq_state = opaque;
+    struct ICH9_LPCState *ich9_lpc = irq_state->lpc;
+
+    if (ich9_lpc->apic_mode)
+        ich9_lpc_set_irq_apic(ich9_lpc, irq_state->ioapic, irq_num, level);
+    else
+        ich9_lpc_set_irq_pic(ich9_lpc, irq_state->pic, irq_num, level);
+}
+
 /* APM */
 static void ich9_apm_ctrl_changed(uint32_t val, void *arg)
 {
diff --git a/hw/q35.h b/hw/q35.h
index a3a97b5..2f68152 100644
--- a/hw/q35.h
+++ b/hw/q35.h
@@ -25,7 +25,8 @@
 #include "acpi_ich9.h"
 
 void gmch_init_memory_mappings(PCIDevice *d);
-PCIBus *gmch_init(PCIDevice **pgmch_state, qemu_irq *pic, int *ich9_lpc_devfn);
+PCIBus *gmch_init(PCIDevice **pgmch_state, qemu_irq *pic, int *ich9_lpc_devfn,
+                  qemu_irq **ioapic);
 
 PCIBus *ich9_d2pbr_init(PCIBus *bus, int devfn, int secondary_bus_num);
 
@@ -176,6 +177,9 @@ void ich9_hot_add_init(struct ich9_lpc_pm_regs *pm);
 #define  ICH9_LPC_RCBA_EN                       0x1
 #define  ICH9_LPC_RCBA_DEFAULT                  0x0
 
+#define ICH9_LPC_PIC_NUM_PINS                   16
+#define ICH9_LPC_IOAPIC_NUM_PINS                24
+
 /* D30:F1 power management I/O registers
    offset from the address ICH9_LPC_PMBASE */
 
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [Qemu-devel] Re: [PATCH 38/61] pci: fix pci_default_write_config()
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 38/61] pci: fix pci_default_write_config() Isaku Yamahata
@ 2009-09-30 10:44   ` Michael S. Tsirkin
  2009-09-30 11:09     ` Isaku Yamahata
  0 siblings, 1 reply; 84+ messages in thread
From: Michael S. Tsirkin @ 2009-09-30 10:44 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Wed, Sep 30, 2009 at 07:18:14PM +0900, Isaku Yamahata wrote:
> When updated ROM expantion address of header type 0,
> it missed to update mappings.

Can the bugfix be separated from proposed optimization please?
It should be a one-liner.

> By using helper functions this patch also avoids memcpy() and memcmp().

I expect this is all slow-path done during boot, so an extra memcpy
operation can not hurt.

I actually think keeping the original copy around is a good thing,
we probably should put it in PCI structure, so that devices can easily
check whether some value was changed.

For example, in your patch pci_update_mappings is called even if none of
the values are changed, or if memory is disabled, and
you also don't seem to update mappings when memory is enabled/disabled.

> Cc: Michael S. Tsirkin <mst@redhat.com>
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
>  hw/pci.c |   11 +++++------
>  hw/pci.h |    9 ++++++++-
>  2 files changed, 13 insertions(+), 7 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index 757fe7b..2a59667 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -627,20 +627,19 @@ uint32_t pci_default_read_config(PCIDevice *d,
>  
>  void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
>  {
> -    uint8_t orig[PCI_CONFIG_SPACE_SIZE];
>      int i;
>      uint32_t config_size = pcie_config_size(d);
>  
> -    /* not efficient, but simple */
> -    memcpy(orig, d->config, PCI_CONFIG_SPACE_SIZE);
>      for(i = 0; i < l && addr < config_size; val >>= 8, ++i, ++addr) {
>          uint8_t wmask = d->wmask[addr];
>          d->config[addr] = (d->config[addr] & ~wmask) | (val & wmask);
>      }
> -    if (memcmp(orig + PCI_BASE_ADDRESS_0, d->config + PCI_BASE_ADDRESS_0, 24)
> -        || ((orig[PCI_COMMAND] ^ d->config[PCI_COMMAND])
> -            & (PCI_COMMAND_MEMORY | PCI_COMMAND_IO)))
> +
> +    if (pci_config_changed(addr, l,
> +                           PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_5 + 4) ||

How can pci_config_changed know whether some value was
actually changed without looking at original and new value?
IMO it's better to keep the original array around,
and use simple memcmp.

> +        pci_config_changed_with_size(addr, l, PCI_ROM_ADDRESS, 4)) {
>          pci_update_mappings(d);
> +    }
>  }
>  
>  static PCIBus *pci_find_bus_from(PCIBus *from, int bus_num)
> diff --git a/hw/pci.h b/hw/pci.h
> index 26c15c5..3327905 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -121,7 +121,12 @@ static inline int pci_bar_is_64bit(const PCIIORegion *r)
>  #define  PCI_HEADER_TYPE_BRIDGE		1
>  #define  PCI_HEADER_TYPE_CARDBUS	2
>  #define  PCI_HEADER_TYPE_MULTI_FUNCTION 0x80
> -#define PCI_BASE_ADDRESS_0	0x10	/* 32 bits */
> +#define PCI_BASE_ADDRESS_0      0x10    /* 32 bits */
> +#define PCI_BASE_ADDRESS_1      0x14    /* 32 bits [htype 0,1 only] */
> +#define PCI_BASE_ADDRESS_2      0x18    /* 32 bits [htype 0 only] */
> +#define PCI_BASE_ADDRESS_3      0x1c    /* 32 bits */
> +#define PCI_BASE_ADDRESS_4      0x20    /* 32 bits */
> +#define PCI_BASE_ADDRESS_5      0x24    /* 32 bits */
>  #define PCI_PRIMARY_BUS		0x18	/* Primary bus number */
>  #define PCI_SECONDARY_BUS	0x19	/* Secondary bus number */
>  #define PCI_SEC_STATUS		0x1e	/* Secondary status register, only bit 14 used */
> @@ -141,7 +146,9 @@ static inline int pci_bar_is_64bit(const PCIIORegion *r)
>  #define PCI_SUBVENDOR_ID        0x2c    /* obsolete, use PCI_SUBSYSTEM_VENDOR_ID */
>  #define PCI_SUBDEVICE_ID        0x2e    /* obsolete, use PCI_SUBSYSTEM_ID */
>  
> +#define PCI_ROM_ADDRESS         0x30    /* Bits 31..11 are address, 10..1 reserved */
>  #define  PCI_ROM_ADDRESS_ENABLE 0x01
> +#define PCI_ROM_ADDRESS_MASK    (~0x7ffUL)
>  
>  /* Bits in the PCI Status Register (PCI 2.3 spec) */
>  #define PCI_STATUS_RESERVED1	0x007
> -- 
> 1.6.0.2

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [Qemu-devel] Re: [PATCH 32/61] pci: helper functions to access PCIDevice::config
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 32/61] pci: helper functions to access PCIDevice::config Isaku Yamahata
@ 2009-09-30 10:47   ` Michael S. Tsirkin
  0 siblings, 0 replies; 84+ messages in thread
From: Michael S. Tsirkin @ 2009-09-30 10:47 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Wed, Sep 30, 2009 at 07:18:08PM +0900, Isaku Yamahata wrote:
> add helper functions to get/set PCIDevice::config
> Those will be used later.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
>  hw/pci.h |   60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 60 insertions(+), 0 deletions(-)
> 
> diff --git a/hw/pci.h b/hw/pci.h
> index 460a2b5..e3f5df8 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -325,6 +325,18 @@ pci_get_long(uint8_t *config)
>  }
>  
>  static inline void
> +pci_set_quad(uint8_t *config, uint64_t val)
> +{
> +    cpu_to_le64w((uint64_t *)config, val);
> +}
> +
> +static inline uint64_t
> +pci_get_quad(uint8_t *config)
> +{
> +    return le64_to_cpup((uint64_t *)config);
> +}
> +
> +static inline void
>  pci_config_set_vendor_id(uint8_t *pci_config, uint16_t val)
>  {
>      pci_set_word(&pci_config[PCI_VENDOR_ID], val);

These look good, provided they are used.

> @@ -342,6 +354,54 @@ pci_config_set_class(uint8_t *pci_config, uint16_t val)
>      pci_set_word(&pci_config[PCI_CLASS_DEVICE], val);
>  }
>  
> +static inline void
> +pci_config_set_byte(PCIDevice *d, uint32_t addr, uint8_t val)
> +{
> +    pci_set_byte(&d->config[addr], val);
> +}
> +
> +static inline void
> +pci_config_set_word(PCIDevice *d, uint32_t addr, uint16_t val)
> +{
> +    pci_set_word(&d->config[addr], val);
> +}
> +
> +static inline void
> +pci_config_set_long(PCIDevice *d, uint32_t addr, uint32_t val)
> +{
> +    pci_set_long(&d->config[addr], val);
> +}
> +
> +static inline void
> +pci_config_set_quad(PCIDevice *d, uint32_t addr, uint64_t val)
> +{
> +    pci_set_quad(&d->config[addr], val);
> +}
> +
> +static inline uint8_t
> +pci_config_get_byte(PCIDevice *d, uint32_t addr)
> +{
> +    return pci_get_byte(&d->config[addr]);
> +}
> +
> +static inline uint16_t
> +pci_config_get_word(PCIDevice *d, uint32_t addr)
> +{
> +    return pci_get_word(&d->config[addr]);
> +}
> +
> +static inline uint32_t
> +pci_config_get_long(PCIDevice *d, uint32_t addr)
> +{
> +    return pci_get_long(&d->config[addr]);
> +}
> +
> +static inline uint64_t
> +pci_config_get_quad(PCIDevice *d, uint32_t addr)
> +{
> +    return pci_get_quad(&d->config[addr]);
> +}
> +

These seem like unnecessary wrappers. PCI is all little
endian: both memory and configuration.

>  typedef int (*pci_qdev_initfn)(PCIDevice *dev);
>  typedef struct {
>      DeviceInfo qdev;
> -- 
> 1.6.0.2
> 
> 

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [Qemu-devel] Re: [PATCH 38/61] pci: fix pci_default_write_config()
  2009-09-30 10:44   ` [Qemu-devel] " Michael S. Tsirkin
@ 2009-09-30 11:09     ` Isaku Yamahata
  2009-09-30 12:50       ` Michael S. Tsirkin
  0 siblings, 1 reply; 84+ messages in thread
From: Isaku Yamahata @ 2009-09-30 11:09 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel

On Wed, Sep 30, 2009 at 12:44:46PM +0200, Michael S. Tsirkin wrote:
> On Wed, Sep 30, 2009 at 07:18:14PM +0900, Isaku Yamahata wrote:
> > When updated ROM expantion address of header type 0,
> > it missed to update mappings.
> 
> Can the bugfix be separated from proposed optimization please?
> It should be a one-liner.

Will do.


> > By using helper functions this patch also avoids memcpy() and memcmp().
> 
> I expect this is all slow-path done during boot, so an extra memcpy
> operation can not hurt.
> I actually think keeping the original copy around is a good thing,
> we probably should put it in PCI structure, so that devices can easily
> check whether some value was changed.

Yes, I agree that it's slow path.
In fact I did it having PCI express support in mind.
PCI express has 4K bytes config space instead of 256 bytes.
I suppose 4K is a bit large for stack/memcpy/memcmp to detect
at most 4 bytes change.
So Optimization to remember 4 bytes (+ alignment?) and
compare is what you want.


> For example, in your patch pci_update_mappings is called even if none of
> the values are changed, or if memory is disabled, and
> you also don't seem to update mappings when memory is enabled/disabled.

It's slow path, isn't it?
And pci_update_mapppings() takes care of such cases.


> > Cc: Michael S. Tsirkin <mst@redhat.com>
> > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> > ---
> >  hw/pci.c |   11 +++++------
> >  hw/pci.h |    9 ++++++++-
> >  2 files changed, 13 insertions(+), 7 deletions(-)
> > 
> > diff --git a/hw/pci.c b/hw/pci.c
> > index 757fe7b..2a59667 100644
> > --- a/hw/pci.c
> > +++ b/hw/pci.c
> > @@ -627,20 +627,19 @@ uint32_t pci_default_read_config(PCIDevice *d,
> >  
> >  void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
> >  {
> > -    uint8_t orig[PCI_CONFIG_SPACE_SIZE];
> >      int i;
> >      uint32_t config_size = pcie_config_size(d);
> >  
> > -    /* not efficient, but simple */
> > -    memcpy(orig, d->config, PCI_CONFIG_SPACE_SIZE);
> >      for(i = 0; i < l && addr < config_size; val >>= 8, ++i, ++addr) {
> >          uint8_t wmask = d->wmask[addr];
> >          d->config[addr] = (d->config[addr] & ~wmask) | (val & wmask);
> >      }
> > -    if (memcmp(orig + PCI_BASE_ADDRESS_0, d->config + PCI_BASE_ADDRESS_0, 24)
> > -        || ((orig[PCI_COMMAND] ^ d->config[PCI_COMMAND])
> > -            & (PCI_COMMAND_MEMORY | PCI_COMMAND_IO)))
> > +
> > +    if (pci_config_changed(addr, l,
> > +                           PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_5 + 4) ||
> 
> How can pci_config_changed know whether some value was
> actually changed without looking at original and new value?
> IMO it's better to keep the original array around,
> and use simple memcmp.
> 
> > +        pci_config_changed_with_size(addr, l, PCI_ROM_ADDRESS, 4)) {
> >          pci_update_mappings(d);
> > +    }
> >  }
> >  
> >  static PCIBus *pci_find_bus_from(PCIBus *from, int bus_num)
> > diff --git a/hw/pci.h b/hw/pci.h
> > index 26c15c5..3327905 100644
> > --- a/hw/pci.h
> > +++ b/hw/pci.h
> > @@ -121,7 +121,12 @@ static inline int pci_bar_is_64bit(const PCIIORegion *r)
> >  #define  PCI_HEADER_TYPE_BRIDGE		1
> >  #define  PCI_HEADER_TYPE_CARDBUS	2
> >  #define  PCI_HEADER_TYPE_MULTI_FUNCTION 0x80
> > -#define PCI_BASE_ADDRESS_0	0x10	/* 32 bits */
> > +#define PCI_BASE_ADDRESS_0      0x10    /* 32 bits */
> > +#define PCI_BASE_ADDRESS_1      0x14    /* 32 bits [htype 0,1 only] */
> > +#define PCI_BASE_ADDRESS_2      0x18    /* 32 bits [htype 0 only] */
> > +#define PCI_BASE_ADDRESS_3      0x1c    /* 32 bits */
> > +#define PCI_BASE_ADDRESS_4      0x20    /* 32 bits */
> > +#define PCI_BASE_ADDRESS_5      0x24    /* 32 bits */
> >  #define PCI_PRIMARY_BUS		0x18	/* Primary bus number */
> >  #define PCI_SECONDARY_BUS	0x19	/* Secondary bus number */
> >  #define PCI_SEC_STATUS		0x1e	/* Secondary status register, only bit 14 used */
> > @@ -141,7 +146,9 @@ static inline int pci_bar_is_64bit(const PCIIORegion *r)
> >  #define PCI_SUBVENDOR_ID        0x2c    /* obsolete, use PCI_SUBSYSTEM_VENDOR_ID */
> >  #define PCI_SUBDEVICE_ID        0x2e    /* obsolete, use PCI_SUBSYSTEM_ID */
> >  
> > +#define PCI_ROM_ADDRESS         0x30    /* Bits 31..11 are address, 10..1 reserved */
> >  #define  PCI_ROM_ADDRESS_ENABLE 0x01
> > +#define PCI_ROM_ADDRESS_MASK    (~0x7ffUL)
> >  
> >  /* Bits in the PCI Status Register (PCI 2.3 spec) */
> >  #define PCI_STATUS_RESERVED1	0x007
> 

-- 
yamahata

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [Qemu-devel] Re: [PATCH 37/61] pci: add helper function for pci config write function to check address.
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 37/61] pci: add helper function for pci config write function to check address Isaku Yamahata
@ 2009-09-30 11:50   ` Michael S. Tsirkin
  0 siblings, 0 replies; 84+ messages in thread
From: Michael S. Tsirkin @ 2009-09-30 11:50 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Wed, Sep 30, 2009 at 07:18:13PM +0900, Isaku Yamahata wrote:
> add helper function for pci config write function to check address.
> Those function will be used later.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
>  hw/pci.h |   14 ++++++++++++++
>  1 files changed, 14 insertions(+), 0 deletions(-)
> 
> diff --git a/hw/pci.h b/hw/pci.h
> index 5cd882c..26c15c5 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -406,6 +406,20 @@ pci_config_get_quad(PCIDevice *d, uint32_t addr)
>      return pci_get_quad(&d->config[addr]);
>  }
>  
> +static inline int pci_config_changed(uint32_t addr, uint32_t len,
> +                              uint32_t base, uint32_t end)
> +{
> +    /* check if [addr, addr + len] intersects [base, end] */
> +    return base <= addr + len && addr <= end;
> +}
> +
> +static inline int pci_config_changed_with_size(uint32_t addr, uint32_t len,
> +                                        uint32_t base, uint32_t size)
> +{
> +    /* check if [addr, addr + len] intersects [base, base + size] */
> +    return base <= addr + len && addr <= base + size;
> +}
> +

This does not really check whether the value was changed:
just that transaction touched it, the new value could be same
as old.

What I think we should do, is on each config access,
store the previous config inside pci device structure.
Then to see whether something changed, you just do
a memcpy, or pci_get_word(d->orig) != pci_get_word(d->config),
or anything you like, and no need for wrappers.


>  typedef int (*pci_qdev_initfn)(PCIDevice *dev);
>  typedef struct {
>      DeviceInfo qdev;
> -- 
> 1.6.0.2
> 
> 

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [Qemu-devel] Re: [PATCH 36/61] pci: use QLIST_ macro instead of direct list manipulation.
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 36/61] pci: use QLIST_ macro instead of direct list manipulation Isaku Yamahata
@ 2009-09-30 11:54   ` Michael S. Tsirkin
  0 siblings, 0 replies; 84+ messages in thread
From: Michael S. Tsirkin @ 2009-09-30 11:54 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Wed, Sep 30, 2009 at 07:18:12PM +0900, Isaku Yamahata wrote:
> For maintenance, use QLIST_ macro instead of direct list implementation
> for PCIBus::next which implements singly linked list.
> This patch replace it with QLIST_ macro.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

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

> ---
>  hw/pci.c |   16 +++++++---------
>  1 files changed, 7 insertions(+), 9 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index b358d80..757fe7b 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -45,7 +45,7 @@ struct PCIBus {
>      void *irq_opaque;
>      PCIDevice *devices[256];
>      PCIDevice *parent_dev;
> -    PCIBus *next;
> +    QLIST_ENTRY(PCIBus) next;
>      /* The bus IRQ state is the logical OR of the connected devices.
>         Keep a count of the number of devices with raised IRQs.  */
>      int nirq;
> @@ -70,7 +70,7 @@ static void pci_set_irq(void *opaque, int irq_num, int level);
>  target_phys_addr_t pci_mem_base;
>  static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET;
>  static uint16_t pci_default_sub_device_id = PCI_SUBDEVICE_ID_QEMU;
> -static PCIBus *first_bus;
> +static QLIST_HEAD(, PCIBus) first_bus;
>  static const VMStateDescription vmstate_pcibus = {
>      .name = "PCIBUS",
> @@ -113,8 +113,7 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
>      bus->devfn_min = devfn_min;
>      bus->nirq = nirq;
>      bus->irq_count = qemu_mallocz(nirq * sizeof(bus->irq_count[0]));
> -    bus->next = first_bus;
> -    first_bus = bus;
> +    QLIST_INSERT_HEAD(&first_bus, bus, next);
>      vmstate_register(nbus++, &vmstate_pcibus, bus);
>      qemu_register_reset(pci_bus_reset, bus);
>      return bus;
> @@ -129,8 +128,7 @@ static PCIBus *pci_register_secondary_bus(PCIDevice *dev,
>      bus = FROM_QBUS(PCIBus, qbus_create(&pci_bus_info, &dev->qdev, name));
>      bus->map_irq = map_irq;
>      bus->parent_dev = dev;
> -    bus->next = dev->bus->next;
> -    dev->bus->next = bus;
> +    QLIST_INSERT_AFTER(dev->bus, bus, next);
>      return bus;
>  }
>  
> @@ -650,7 +648,7 @@ static PCIBus *pci_find_bus_from(PCIBus *from, int bus_num)
>      PCIBus *s = from;
>  
>      while (s && s->bus_num != bus_num)
> -        s = s->next;
> +        s = QLIST_NEXT(s, next);
>  
>      return s;
>  }
> @@ -1025,7 +1023,7 @@ static void pci_info_device(PCIDevice *d)
>  
>  void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d))
>  {
> -    PCIBus *bus = first_bus;
> +    PCIBus *bus = QLIST_FIRST(&first_bus);
>      PCIDevice *d;
>      int devfn;
>  
> @@ -1129,7 +1127,7 @@ static void pci_bridge_write_config(PCIDevice *d,
>  
>  PCIBus *pci_find_bus(int bus_num)
>  {
> -    return pci_find_bus_from(first_bus, bus_num);
> +    return pci_find_bus_from(QLIST_FIRST(&first_bus), bus_num);
>  }
>  
>  PCIDevice *pci_find_device(int bus_num, int slot, int function)
> -- 
> 1.6.0.2
> 
> 

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [Qemu-devel] Re: [PATCH 22/61] pci: use appropriate PRIs in PCI_DPRINTF().
  2009-09-30 10:17 ` [Qemu-devel] [PATCH 22/61] pci: use appropriate PRIs in PCI_DPRINTF() Isaku Yamahata
@ 2009-09-30 11:55   ` Michael S. Tsirkin
  2009-10-01  7:22     ` Isaku Yamahata
  0 siblings, 1 reply; 84+ messages in thread
From: Michael S. Tsirkin @ 2009-09-30 11:55 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Wed, Sep 30, 2009 at 07:17:58PM +0900, Isaku Yamahata wrote:
> use appropriate PRIs in PCI_DPRINTF() for portability.
> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>


I'm confused. Shouldn't we be getting 64 bit now?

> ---
>  hw/pci.c |   10 ++++++----
>  1 files changed, 6 insertions(+), 4 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index 5c59092..4a7568d 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -561,7 +561,7 @@ void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
>      int config_addr, bus_num;
>  
>  #if 0
> -    PCI_DPRINTF("pci_data_write: addr=%08x val=%08x len=%d\n",
> +    PCI_DPRINTF("pci_data_write: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
>                  addr, val, len);
>  #endif
>      bus_num = (addr >> 16) & 0xff;
> @@ -573,7 +573,8 @@ void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
>      if (!pci_dev)
>          return;
>      config_addr = addr & 0xff;
> -    PCI_DPRINTF("pci_config_write: %s: addr=%02x val=%08x len=%d\n",
> +    PCI_DPRINTF("pci_config_write: %s: "
> +                "addr=%02"PRIx32" val=%08"PRI32x" len=%d\n",
>                  pci_dev->name, config_addr, val, len);
>      pci_dev->config_write(pci_dev, config_addr, val, len);
>  }
> @@ -609,11 +610,12 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
>      }
>      config_addr = addr & 0xff;
>      val = pci_dev->config_read(pci_dev, config_addr, len);
> -    PCI_DPRINTF("pci_config_read: %s: addr=%02x val=%08x len=%d\n",
> +    PCI_DPRINTF("pci_config_read: %s: "
> +                "addr=%02"PRIx32" val=%08"PRIx32" len=%d\n",
>                  pci_dev->name, config_addr, val, len);
>   the_end:
>  #if 0
> -    PCI_DPRINTF("pci_data_read: addr=%08x val=%08x len=%d\n",
> +    PCI_DPRINTF("pci_data_read: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
>                  addr, val, len);
>  #endif
>      return val;
> -- 
> 1.6.0.2
> 
> 

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [Qemu-devel] Re: [PATCH 00/61] Q35 chip set and stuff.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (60 preceding siblings ...)
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 61/61] pc_q35: apic mode for pci interrupt routing Isaku Yamahata
@ 2009-09-30 12:00 ` Michael S. Tsirkin
  2009-09-30 12:08 ` [Qemu-devel] " Aurelien Jarno
                   ` (2 subsequent siblings)
  64 siblings, 0 replies; 84+ messages in thread
From: Michael S. Tsirkin @ 2009-09-30 12:00 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Wed, Sep 30, 2009 at 07:17:36PM +0900, Isaku Yamahata wrote:
> This patch set is for Q35 chipset(GMCH and ICH9) based PC.
> 
> Anthony,
> I'm aware that this patch set is already conflicting to other's patches.
> Which tree/changeset do you want me to rebase?
> Your staging qemu repo doesn't seem to include the latest patches.
> As I'm seeing regular patch conflicts, I need your help as a maintainer.
> 
> The motivation is to support newer hardware features because
> piix chipset is very old.
> Especially I have PCI express in mind and this is the basic
> infrastructure for PCI express hot plug and PCI express native 
> direct attach.
> With this patch set, you can see PCIe MMCONFIG space and 3+ PCI busses.
> I haven't implemented PCI express port/switch and PCI express hot plug.
> This is my next TODO. and then PCI express native direct attach/passthrough
> 
> I can boot Linux 2.6.30 with PCIe MMCONFIG with APIC mode pci interrupt
> routing. I haven't tested other OSes.
> (I patches linux kernel to test MMCONFIG because Linux uses conventional
> IO port to PCI config space, i.e. 256)
> To use this patch, bios also needs patches I'll sent out soon.
> 
> 
> Firstly this patch set splits up current piix pc code into
> piix specific code and common code.
> Those patches are almost same as the one I sent out before.
> And then PCI related patches comes in. They cleans up PCI related code
> , implements PCIe MMCONFIG and fixes PCI bridge.
> Thirdly q35 chipset is implemented.
> Lastly IO apic related 

I don't really understand how these relate to pci patches
you posted and some of which I acked previously.

> Changes from split out piix specific part from pc emulator. V6
> - rebased to 731c54f86988d3f28268f184fabfe9b2a32fb5d3
> - PCIe MMCONFIG
> - pci bridge related fixes
> - chipset emulator works.
> - IOAPIC patches
> 
> Changes from v5:
> - rebased 0.11.0-rc0
> - changed qemu_system_powerdown_register() to call
>   qemu_system_shutdown_request() if qemu_system_shutdown() is called before
>   registering.
> 
> Changes from v4:
> - fix version number.
> - rebased anthony's staging tree whose latest change set is
>   62969268f876c547ee64da6d60e0f363e0f1df75
> 
> Changes from v3:
> - move qemu_system_powerdown() in vl.c and more generic
>   following the comment by Marcelo Tosatti <mtosatti@redhat.com>
>   acpi.c: make qemu_system_powerdown() piix independent.
> - define cmos_set_s3_resume_init() and cmos_set_s3_resume() in pc.c
>   even if TARGET_I386 isn't defined following th ecommit by
>   Paolo Bonzini <bonzini@gnu.org>
>   pc.c: remove a global variable, RTCState *rtc_state.
> - minor compilation fixes
> 
> Changes from v2:
> - clean up pc_pci_device_init() not to use unnecessary braces.
> 
> Changes from v1:
> - make patches full bisectable
> - typo s/allocte/allocate/
> - some minor fixes
> - dropped a merged patch
> 
> 
> Isaku Yamahata (61):
>   acpi: split out pc smbus routines from acpi.c into pc_smbus.c
>   acpi: split out apm register emulation from acpi.c
>   acpi: add acpi constants from linux header files and use them.
>   acpi: split acpi.c into the common part and the piix4 part.
>   acpi_piix4: remove unused variable in get_pmsts().
>   pc: fix file stream leak in multiboot loader.
>   pc, i440fx: Make smm enable/disable function i440fx independent.
>   pc: make an unnecessary global variable, pit, local.
>   pc: remove a global variable, floppy_controller.
>   pc: remove a global variable, RTCState *rtc_state.
>   pc: introduce a function to allocate cpu irq.
>   pc: make pc_init1() not refer ferr_irq directly.
>   pc: split out cpu initialization from pc_init1() into pc_cpus_init().
>   pc: split out memory allocation from pc_init1() into pc_memory_init()
>   pc: split out vga initialization from pc_init1() into pc_vga_init().
>   pc: split out basic device init from pc_init1() into
>     pc_basic_device_init()
>   pc: split out pci device init from pc_init1() into
>     pc_pci_device_init()
>   pc: split out piix specific part from pc.c into pc_piix.c
>   pc_piix: initialize ioapic before use.
>   pci: fix PCI_DPRINTF() wrt variadic macro.
>   pci: introduce constant PCI_NUM_PINS for the number of interrupt
>     pins, 4.
>   pci: use appropriate PRIs in PCI_DPRINTF().
>   pci: use PCI_SLOT() and PCI_FUNC().
>   pci: define a constant to represent a unmapped bar and use it.
>   pci: use uint64_t for bar addr and size instead of uint32_t.
>   pci: 64bit bar support.
>   pci: clean up of pci_update_mappings()
>   pci: factor out while(bus) bus->next loop logic into
>     pci_find_bus_from().
>   pci: factor out the logic to get pci device from address.
>   pci_host.h: split non-inline static function in pci_host.h into
>     pci_host_c.h
>   pci: pcie host and mmcfg support.
>   pci: helper functions to access PCIDevice::config
>   pci: use the symbolic constant, PCI_ROM_ADDRESS_ENABLE instead of 1.
>   pci: introduce pci_swizzle_map_irq_fn() for interrupt pin swizzle.
>   piix_pci: use pci_swizzle_map_irq_fn().
>   pci: use QLIST_ macro instead of direct list manipulation.
>   pci: add helper function for pci config write function to check
>     address.
>   pci: fix pci_default_write_config()
>   pci: factor out config update logic.
>   pci: use qdev to get parent bus with PCIBus.
>   pci: make bar update function aware of pci bridge.
>   pci/brdige: qdevfy and initialize secondary bus and subordinate bus.
>   pci: add helper function to initialize wmask.
>   pci: initialize wmask according to pci header type.
>   pci/monitor: print out bridge's filtering values and so on.
>   pci/bridge: implement intel 82801ba bridge.
>   pci.h: add more status constats.
>   pci id: add subclass codes for serial device.
>   pci hot add: pass opaque argument to callback.
>   pci hotadd, acpi_piix4: remove global variables.
>   vmstate: add a macro for pointer to struct, VMSTATE_STRUCT_POINTER.
>   pci: add a hook to replace default pci bus instead of 0 bus.
>   pc q35 based chipset emulator
>   pci: add opaque argument to pci_map_irq_fn().
>   ioapic: make ioapic_set_irq() static.
>   ioapic: clean up of  #ifdef DEBUG_IOAPIC.
>   ioapic: add callback when entry is set or ioapic is reset
>   ioapic: make the number of pins configurable.
>   ioapic: make irr accept more than 32 pins.
>   pci: add opaque arg to pci_map_irq_fn.
>   pc_q35: apic mode for pci interrupt routing.
> 
>  Makefile.target                 |    5 +-
>  hw/ac97.c                       |    2 +-
>  hw/acpi.c                       |  736 +--------------------------
>  hw/acpi.h                       |   78 +++
>  hw/acpi_ich9.c                  |  565 ++++++++++++++++++++
>  hw/acpi_ich9.h                  |   57 ++
>  hw/acpi_piix4.c                 |  582 +++++++++++++++++++++
>  hw/apb_pci.c                    |   16 +-
>  hw/cirrus_vga.c                 |    8 +-
>  hw/e1000.c                      |   12 +-
>  hw/eepro100.c                   |   10 +-
>  hw/es1370.c                     |    2 +-
>  hw/grackle_pci.c                |    4 +-
>  hw/gt64xxx.c                    |    4 +-
>  hw/hw.h                         |   42 ++
>  hw/ide/pci.c                    |    4 +-
>  hw/ioapic.c                     |  137 ++++--
>  hw/lsi53c895a.c                 |    6 +-
>  hw/macio.c                      |    2 +-
>  hw/msix.c                       |    2 +-
>  hw/msix.h                       |    2 +-
>  hw/ne2000.c                     |    2 +-
>  hw/openpic.c                    |    2 +-
>  hw/pc.c                         |  344 ++++---------
>  hw/pc.h                         |   48 ++-
>  hw/pc_apm.c                     |   89 ++++
>  hw/pc_apm.h                     |   43 ++
>  hw/pc_piix.c                    |  241 +++++++++
>  hw/pc_q35.c                     |  220 ++++++++
>  hw/pc_smbus.c                   |  178 +++++++
>  hw/pc_smbus.h                   |   43 ++
>  hw/pci-hotplug.c                |    7 +-
>  hw/pci.c                        | 1102 +++++++++++++++++++++++++++++++--------
>  hw/pci.h                        |  261 +++++++++-
>  hw/pci_bridge.c                 |   63 +++
>  hw/pci_bridge.h                 |   38 ++
>  hw/pci_host.h                   |  110 +---
>  hw/{pci_host.h => pci_host_c.h} |    8 +-
>  hw/pci_ids.h                    |   28 +
>  hw/pcnet.c                      |    9 +-
>  hw/piix_pci.c                   |   14 +-
>  hw/ppc4xx_pci.c                 |    4 +-
>  hw/ppce500_pci.c                |    4 +-
>  hw/prep_pci.c                   |    4 +-
>  hw/q35.c                        |  784 ++++++++++++++++++++++++++++
>  hw/q35.h                        |  232 ++++++++
>  hw/q35_smbus.c                  |  150 ++++++
>  hw/r2d.c                        |    2 +-
>  hw/rtl8139.c                    |    4 +-
>  hw/sun4u.c                      |    2 +-
>  hw/unin_pci.c                   |    4 +-
>  hw/usb-ohci.c                   |    2 +-
>  hw/usb-uhci.c                   |    2 +-
>  hw/versatile_pci.c              |    2 +-
>  hw/vga-pci.c                    |    2 +-
>  hw/virtio-pci.c                 |    2 +-
>  hw/vmware_vga.c                 |    4 +-
>  hw/wdt_i6300esb.c               |    5 +-
>  sysemu.h                        |    4 +-
>  59 files changed, 4932 insertions(+), 1407 deletions(-)
>  create mode 100644 hw/acpi.h
>  create mode 100644 hw/acpi_ich9.c
>  create mode 100644 hw/acpi_ich9.h
>  create mode 100644 hw/acpi_piix4.c
>  create mode 100644 hw/pc_apm.c
>  create mode 100644 hw/pc_apm.h
>  create mode 100644 hw/pc_piix.c
>  create mode 100644 hw/pc_q35.c
>  create mode 100644 hw/pc_smbus.c
>  create mode 100644 hw/pc_smbus.h
>  create mode 100644 hw/pci_bridge.c
>  create mode 100644 hw/pci_bridge.h
>  copy hw/{pci_host.h => pci_host_c.h} (96%)
>  create mode 100644 hw/q35.c
>  create mode 100644 hw/q35.h
>  create mode 100644 hw/q35_smbus.c
> 
> 

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (61 preceding siblings ...)
  2009-09-30 12:00 ` [Qemu-devel] Re: [PATCH 00/61] Q35 chip set and stuff Michael S. Tsirkin
@ 2009-09-30 12:08 ` Aurelien Jarno
  2009-10-01  5:40   ` Isaku Yamahata
  2009-09-30 18:37 ` Blue Swirl
  2009-09-30 20:53 ` [Qemu-devel] " Anthony Liguori
  64 siblings, 1 reply; 84+ messages in thread
From: Aurelien Jarno @ 2009-09-30 12:08 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

Isaku Yamahata a écrit :
> This patch set is for Q35 chipset(GMCH and ICH9) based PC.

Nice work?

Do you also plan to implement the GMA (integrated graphic card), and the
IOMMU with this chipset? If not it may be better to call it P35.


> Anthony,
> I'm aware that this patch set is already conflicting to other's patches.
> Which tree/changeset do you want me to rebase?
> Your staging qemu repo doesn't seem to include the latest patches.
> As I'm seeing regular patch conflicts, I need your help as a maintainer.
> 
> The motivation is to support newer hardware features because
> piix chipset is very old.
> Especially I have PCI express in mind and this is the basic
> infrastructure for PCI express hot plug and PCI express native 
> direct attach.
> With this patch set, you can see PCIe MMCONFIG space and 3+ PCI busses.
> I haven't implemented PCI express port/switch and PCI express hot plug.
> This is my next TODO. and then PCI express native direct attach/passthrough
> 
> I can boot Linux 2.6.30 with PCIe MMCONFIG with APIC mode pci interrupt
> routing. I haven't tested other OSes.
> (I patches linux kernel to test MMCONFIG because Linux uses conventional
> IO port to PCI config space, i.e. 256)
> To use this patch, bios also needs patches I'll sent out soon.
> 
> 
> Firstly this patch set splits up current piix pc code into
> piix specific code and common code.
> Those patches are almost same as the one I sent out before.
> And then PCI related patches comes in. They cleans up PCI related code
> , implements PCIe MMCONFIG and fixes PCI bridge.
> Thirdly q35 chipset is implemented.
> Lastly IO apic related 
> 
> Changes from split out piix specific part from pc emulator. V6
> - rebased to 731c54f86988d3f28268f184fabfe9b2a32fb5d3
> - PCIe MMCONFIG
> - pci bridge related fixes
> - chipset emulator works.
> - IOAPIC patches
> 
> Changes from v5:
> - rebased 0.11.0-rc0
> - changed qemu_system_powerdown_register() to call
>   qemu_system_shutdown_request() if qemu_system_shutdown() is called before
>   registering.
> 
> Changes from v4:
> - fix version number.
> - rebased anthony's staging tree whose latest change set is
>   62969268f876c547ee64da6d60e0f363e0f1df75
> 
> Changes from v3:
> - move qemu_system_powerdown() in vl.c and more generic
>   following the comment by Marcelo Tosatti <mtosatti@redhat.com>
>   acpi.c: make qemu_system_powerdown() piix independent.
> - define cmos_set_s3_resume_init() and cmos_set_s3_resume() in pc.c
>   even if TARGET_I386 isn't defined following th ecommit by
>   Paolo Bonzini <bonzini@gnu.org>
>   pc.c: remove a global variable, RTCState *rtc_state.
> - minor compilation fixes
> 
> Changes from v2:
> - clean up pc_pci_device_init() not to use unnecessary braces.
> 
> Changes from v1:
> - make patches full bisectable
> - typo s/allocte/allocate/
> - some minor fixes
> - dropped a merged patch
> 
> 
> Isaku Yamahata (61):
>   acpi: split out pc smbus routines from acpi.c into pc_smbus.c
>   acpi: split out apm register emulation from acpi.c
>   acpi: add acpi constants from linux header files and use them.
>   acpi: split acpi.c into the common part and the piix4 part.
>   acpi_piix4: remove unused variable in get_pmsts().
>   pc: fix file stream leak in multiboot loader.
>   pc, i440fx: Make smm enable/disable function i440fx independent.
>   pc: make an unnecessary global variable, pit, local.
>   pc: remove a global variable, floppy_controller.
>   pc: remove a global variable, RTCState *rtc_state.
>   pc: introduce a function to allocate cpu irq.
>   pc: make pc_init1() not refer ferr_irq directly.
>   pc: split out cpu initialization from pc_init1() into pc_cpus_init().
>   pc: split out memory allocation from pc_init1() into pc_memory_init()
>   pc: split out vga initialization from pc_init1() into pc_vga_init().
>   pc: split out basic device init from pc_init1() into
>     pc_basic_device_init()
>   pc: split out pci device init from pc_init1() into
>     pc_pci_device_init()
>   pc: split out piix specific part from pc.c into pc_piix.c
>   pc_piix: initialize ioapic before use.
>   pci: fix PCI_DPRINTF() wrt variadic macro.
>   pci: introduce constant PCI_NUM_PINS for the number of interrupt
>     pins, 4.
>   pci: use appropriate PRIs in PCI_DPRINTF().
>   pci: use PCI_SLOT() and PCI_FUNC().
>   pci: define a constant to represent a unmapped bar and use it.
>   pci: use uint64_t for bar addr and size instead of uint32_t.
>   pci: 64bit bar support.
>   pci: clean up of pci_update_mappings()
>   pci: factor out while(bus) bus->next loop logic into
>     pci_find_bus_from().
>   pci: factor out the logic to get pci device from address.
>   pci_host.h: split non-inline static function in pci_host.h into
>     pci_host_c.h
>   pci: pcie host and mmcfg support.
>   pci: helper functions to access PCIDevice::config
>   pci: use the symbolic constant, PCI_ROM_ADDRESS_ENABLE instead of 1.
>   pci: introduce pci_swizzle_map_irq_fn() for interrupt pin swizzle.
>   piix_pci: use pci_swizzle_map_irq_fn().
>   pci: use QLIST_ macro instead of direct list manipulation.
>   pci: add helper function for pci config write function to check
>     address.
>   pci: fix pci_default_write_config()
>   pci: factor out config update logic.
>   pci: use qdev to get parent bus with PCIBus.
>   pci: make bar update function aware of pci bridge.
>   pci/brdige: qdevfy and initialize secondary bus and subordinate bus.
>   pci: add helper function to initialize wmask.
>   pci: initialize wmask according to pci header type.
>   pci/monitor: print out bridge's filtering values and so on.
>   pci/bridge: implement intel 82801ba bridge.
>   pci.h: add more status constats.
>   pci id: add subclass codes for serial device.
>   pci hot add: pass opaque argument to callback.
>   pci hotadd, acpi_piix4: remove global variables.
>   vmstate: add a macro for pointer to struct, VMSTATE_STRUCT_POINTER.
>   pci: add a hook to replace default pci bus instead of 0 bus.
>   pc q35 based chipset emulator
>   pci: add opaque argument to pci_map_irq_fn().
>   ioapic: make ioapic_set_irq() static.
>   ioapic: clean up of  #ifdef DEBUG_IOAPIC.
>   ioapic: add callback when entry is set or ioapic is reset
>   ioapic: make the number of pins configurable.
>   ioapic: make irr accept more than 32 pins.
>   pci: add opaque arg to pci_map_irq_fn.
>   pc_q35: apic mode for pci interrupt routing.
> 
>  Makefile.target                 |    5 +-
>  hw/ac97.c                       |    2 +-
>  hw/acpi.c                       |  736 +--------------------------
>  hw/acpi.h                       |   78 +++
>  hw/acpi_ich9.c                  |  565 ++++++++++++++++++++
>  hw/acpi_ich9.h                  |   57 ++
>  hw/acpi_piix4.c                 |  582 +++++++++++++++++++++
>  hw/apb_pci.c                    |   16 +-
>  hw/cirrus_vga.c                 |    8 +-
>  hw/e1000.c                      |   12 +-
>  hw/eepro100.c                   |   10 +-
>  hw/es1370.c                     |    2 +-
>  hw/grackle_pci.c                |    4 +-
>  hw/gt64xxx.c                    |    4 +-
>  hw/hw.h                         |   42 ++
>  hw/ide/pci.c                    |    4 +-
>  hw/ioapic.c                     |  137 ++++--
>  hw/lsi53c895a.c                 |    6 +-
>  hw/macio.c                      |    2 +-
>  hw/msix.c                       |    2 +-
>  hw/msix.h                       |    2 +-
>  hw/ne2000.c                     |    2 +-
>  hw/openpic.c                    |    2 +-
>  hw/pc.c                         |  344 ++++---------
>  hw/pc.h                         |   48 ++-
>  hw/pc_apm.c                     |   89 ++++
>  hw/pc_apm.h                     |   43 ++
>  hw/pc_piix.c                    |  241 +++++++++
>  hw/pc_q35.c                     |  220 ++++++++
>  hw/pc_smbus.c                   |  178 +++++++
>  hw/pc_smbus.h                   |   43 ++
>  hw/pci-hotplug.c                |    7 +-
>  hw/pci.c                        | 1102 +++++++++++++++++++++++++++++++--------
>  hw/pci.h                        |  261 +++++++++-
>  hw/pci_bridge.c                 |   63 +++
>  hw/pci_bridge.h                 |   38 ++
>  hw/pci_host.h                   |  110 +---
>  hw/{pci_host.h => pci_host_c.h} |    8 +-
>  hw/pci_ids.h                    |   28 +
>  hw/pcnet.c                      |    9 +-
>  hw/piix_pci.c                   |   14 +-
>  hw/ppc4xx_pci.c                 |    4 +-
>  hw/ppce500_pci.c                |    4 +-
>  hw/prep_pci.c                   |    4 +-
>  hw/q35.c                        |  784 ++++++++++++++++++++++++++++
>  hw/q35.h                        |  232 ++++++++
>  hw/q35_smbus.c                  |  150 ++++++
>  hw/r2d.c                        |    2 +-
>  hw/rtl8139.c                    |    4 +-
>  hw/sun4u.c                      |    2 +-
>  hw/unin_pci.c                   |    4 +-
>  hw/usb-ohci.c                   |    2 +-
>  hw/usb-uhci.c                   |    2 +-
>  hw/versatile_pci.c              |    2 +-
>  hw/vga-pci.c                    |    2 +-
>  hw/virtio-pci.c                 |    2 +-
>  hw/vmware_vga.c                 |    4 +-
>  hw/wdt_i6300esb.c               |    5 +-
>  sysemu.h                        |    4 +-
>  59 files changed, 4932 insertions(+), 1407 deletions(-)
>  create mode 100644 hw/acpi.h
>  create mode 100644 hw/acpi_ich9.c
>  create mode 100644 hw/acpi_ich9.h
>  create mode 100644 hw/acpi_piix4.c
>  create mode 100644 hw/pc_apm.c
>  create mode 100644 hw/pc_apm.h
>  create mode 100644 hw/pc_piix.c
>  create mode 100644 hw/pc_q35.c
>  create mode 100644 hw/pc_smbus.c
>  create mode 100644 hw/pc_smbus.h
>  create mode 100644 hw/pci_bridge.c
>  create mode 100644 hw/pci_bridge.h
>  copy hw/{pci_host.h => pci_host_c.h} (96%)
>  create mode 100644 hw/q35.c
>  create mode 100644 hw/q35.h
>  create mode 100644 hw/q35_smbus.c
> 
> 
> 
> 


-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [Qemu-devel] Re: [PATCH 38/61] pci: fix pci_default_write_config()
  2009-09-30 11:09     ` Isaku Yamahata
@ 2009-09-30 12:50       ` Michael S. Tsirkin
  0 siblings, 0 replies; 84+ messages in thread
From: Michael S. Tsirkin @ 2009-09-30 12:50 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Wed, Sep 30, 2009 at 08:09:42PM +0900, Isaku Yamahata wrote:
> On Wed, Sep 30, 2009 at 12:44:46PM +0200, Michael S. Tsirkin wrote:
> > On Wed, Sep 30, 2009 at 07:18:14PM +0900, Isaku Yamahata wrote:
> > > When updated ROM expantion address of header type 0,
> > > it missed to update mappings.
> > 
> > Can the bugfix be separated from proposed optimization please?
> > It should be a one-liner.
> 
> Will do.
> 
> 
> > > By using helper functions this patch also avoids memcpy() and memcmp().
> > 
> > I expect this is all slow-path done during boot, so an extra memcpy
> > operation can not hurt.
> > I actually think keeping the original copy around is a good thing,
> > we probably should put it in PCI structure, so that devices can easily
> > check whether some value was changed.
> 
> Yes, I agree that it's slow path.
> In fact I did it having PCI express support in mind.
> PCI express has 4K bytes config space instead of 256 bytes.
> I suppose 4K is a bit large for stack/memcpy/memcmp to detect
> at most 4 bytes change.
> So Optimization to remember 4 bytes (+ alignment?) and
> compare is what you want.

I don't know if the concern is real. Isn't this premature optimization?
Assuming it is not - the way I would do this, is keep the copy of the
array inside PCI device structure (no stack), and only memcpy the
relevant bytes to keep them in sync. It should be as simple as:
	memcpy(pdev->origin + addr, pdev->config + addr, len)
memcpy is done with a small length, so it is cheap.

> 
> > For example, in your patch pci_update_mappings is called even if none of
> > the values are changed, or if memory is disabled, and
> > you also don't seem to update mappings when memory is enabled/disabled.
> 
> It's slow path, isn't it?

Yes, but you seem add code to optimize it.  FWIW, with a lot of devices,
extra scan will be much slower than a 4K memcpy which might be a single
asm instruction.

> And pci_update_mapppings() takes care of such cases.

Yes but you don't seem to call it e.g. on command write.

> 
> > > Cc: Michael S. Tsirkin <mst@redhat.com>
> > > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> > > ---
> > >  hw/pci.c |   11 +++++------
> > >  hw/pci.h |    9 ++++++++-
> > >  2 files changed, 13 insertions(+), 7 deletions(-)
> > > 
> > > diff --git a/hw/pci.c b/hw/pci.c
> > > index 757fe7b..2a59667 100644
> > > --- a/hw/pci.c
> > > +++ b/hw/pci.c
> > > @@ -627,20 +627,19 @@ uint32_t pci_default_read_config(PCIDevice *d,
> > >  
> > >  void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
> > >  {
> > > -    uint8_t orig[PCI_CONFIG_SPACE_SIZE];
> > >      int i;
> > >      uint32_t config_size = pcie_config_size(d);
> > >  
> > > -    /* not efficient, but simple */
> > > -    memcpy(orig, d->config, PCI_CONFIG_SPACE_SIZE);
> > >      for(i = 0; i < l && addr < config_size; val >>= 8, ++i, ++addr) {
> > >          uint8_t wmask = d->wmask[addr];
> > >          d->config[addr] = (d->config[addr] & ~wmask) | (val & wmask);
> > >      }
> > > -    if (memcmp(orig + PCI_BASE_ADDRESS_0, d->config + PCI_BASE_ADDRESS_0, 24)
> > > -        || ((orig[PCI_COMMAND] ^ d->config[PCI_COMMAND])
> > > -            & (PCI_COMMAND_MEMORY | PCI_COMMAND_IO)))
> > > +
> > > +    if (pci_config_changed(addr, l,
> > > +                           PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_5 + 4) ||
> > 
> > How can pci_config_changed know whether some value was
> > actually changed without looking at original and new value?
> > IMO it's better to keep the original array around,
> > and use simple memcmp.
> > 
> > > +        pci_config_changed_with_size(addr, l, PCI_ROM_ADDRESS, 4)) {
> > >          pci_update_mappings(d);
> > > +    }
> > >  }
> > >  
> > >  static PCIBus *pci_find_bus_from(PCIBus *from, int bus_num)
> > > diff --git a/hw/pci.h b/hw/pci.h
> > > index 26c15c5..3327905 100644
> > > --- a/hw/pci.h
> > > +++ b/hw/pci.h
> > > @@ -121,7 +121,12 @@ static inline int pci_bar_is_64bit(const PCIIORegion *r)
> > >  #define  PCI_HEADER_TYPE_BRIDGE		1
> > >  #define  PCI_HEADER_TYPE_CARDBUS	2
> > >  #define  PCI_HEADER_TYPE_MULTI_FUNCTION 0x80
> > > -#define PCI_BASE_ADDRESS_0	0x10	/* 32 bits */
> > > +#define PCI_BASE_ADDRESS_0      0x10    /* 32 bits */
> > > +#define PCI_BASE_ADDRESS_1      0x14    /* 32 bits [htype 0,1 only] */
> > > +#define PCI_BASE_ADDRESS_2      0x18    /* 32 bits [htype 0 only] */
> > > +#define PCI_BASE_ADDRESS_3      0x1c    /* 32 bits */
> > > +#define PCI_BASE_ADDRESS_4      0x20    /* 32 bits */
> > > +#define PCI_BASE_ADDRESS_5      0x24    /* 32 bits */
> > >  #define PCI_PRIMARY_BUS		0x18	/* Primary bus number */
> > >  #define PCI_SECONDARY_BUS	0x19	/* Secondary bus number */
> > >  #define PCI_SEC_STATUS		0x1e	/* Secondary status register, only bit 14 used */
> > > @@ -141,7 +146,9 @@ static inline int pci_bar_is_64bit(const PCIIORegion *r)
> > >  #define PCI_SUBVENDOR_ID        0x2c    /* obsolete, use PCI_SUBSYSTEM_VENDOR_ID */
> > >  #define PCI_SUBDEVICE_ID        0x2e    /* obsolete, use PCI_SUBSYSTEM_ID */
> > >  
> > > +#define PCI_ROM_ADDRESS         0x30    /* Bits 31..11 are address, 10..1 reserved */
> > >  #define  PCI_ROM_ADDRESS_ENABLE 0x01
> > > +#define PCI_ROM_ADDRESS_MASK    (~0x7ffUL)
> > >  
> > >  /* Bits in the PCI Status Register (PCI 2.3 spec) */
> > >  #define PCI_STATUS_RESERVED1	0x007
> > 
> 
> -- 
> yamahata

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [Qemu-devel] [PATCH 25/61] pci: use uint64_t for bar addr and size instead of uint32_t.
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 25/61] pci: use uint64_t for bar addr and size instead of uint32_t Isaku Yamahata
@ 2009-09-30 14:55   ` malc
  2009-10-01  5:34     ` Isaku Yamahata
  0 siblings, 1 reply; 84+ messages in thread
From: malc @ 2009-09-30 14:55 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Wed, 30 Sep 2009, Isaku Yamahata wrote:

> This patch is preliminary for 64bit bar.
> For 64bit bar support, replace uint32_t with uint64_t for addr/size
> to be able to represent 64bit.

I'm not sure how this supposed to work with devices that are physically
incapable of working with 64bit addresses, care to explain?

[..snip..]

-- 
mailto:av1474@comtv.ru

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (62 preceding siblings ...)
  2009-09-30 12:08 ` [Qemu-devel] " Aurelien Jarno
@ 2009-09-30 18:37 ` Blue Swirl
  2009-09-30 20:53 ` [Qemu-devel] " Anthony Liguori
  64 siblings, 0 replies; 84+ messages in thread
From: Blue Swirl @ 2009-09-30 18:37 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Wed, Sep 30, 2009 at 1:17 PM, Isaku Yamahata <yamahata@valinux.co.jp> wrote:
> This patch set is for Q35 chipset(GMCH and ICH9) based PC.

Tested Sparc64, PPC and PPC64, all OK.

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [Qemu-devel] Re: [PATCH 00/61] Q35 chip set and stuff.
  2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
                   ` (63 preceding siblings ...)
  2009-09-30 18:37 ` Blue Swirl
@ 2009-09-30 20:53 ` Anthony Liguori
  64 siblings, 0 replies; 84+ messages in thread
From: Anthony Liguori @ 2009-09-30 20:53 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

Isaku Yamahata wrote:
> This patch set is for Q35 chipset(GMCH and ICH9) based PC.
>
> Anthony,
> I'm aware that this patch set is already conflicting to other's patches.
> Which tree/changeset do you want me to rebase?
> Your staging qemu repo doesn't seem to include the latest patches.
> As I'm seeing regular patch conflicts, I need your help as a maintainer.
>   

I'd suggest splitting your patchset up into more easily 
reviewable/mergable chunks.  For instance, submit one patch series that 
is simply all of the code movement your series requires.  Submit a 
separate patchset to introduce support for 64-bit PCI, the PCI-e 
adapter, etc.

Then we can merge the easy stuff and focus on reviewing the more 
detailed stuff.  I just tried again to rebase the series and it's just 
too much all at once.

Regards,

Anthony Liguori

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [Qemu-devel] [PATCH 25/61] pci: use uint64_t for bar addr and size instead of uint32_t.
  2009-09-30 14:55   ` malc
@ 2009-10-01  5:34     ` Isaku Yamahata
  0 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-10-01  5:34 UTC (permalink / raw)
  To: malc; +Cc: qemu-devel

On Wed, Sep 30, 2009 at 06:55:51PM +0400, malc wrote:
> On Wed, 30 Sep 2009, Isaku Yamahata wrote:
> 
> > This patch is preliminary for 64bit bar.
> > For 64bit bar support, replace uint32_t with uint64_t for addr/size
> > to be able to represent 64bit.
> 
> I'm not sure how this supposed to work with devices that are physically
> incapable of working with 64bit addresses, care to explain?

Such a device implements only 32bit BAR and never 64bit BAR.
So it gets only 32bit addressable value in uint64_t.
If you want to make sure it, you can insert
assert(address <= UINT32_MAX) into map function of such devices.
-- 
yamahata

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff.
  2009-09-30 12:08 ` [Qemu-devel] " Aurelien Jarno
@ 2009-10-01  5:40   ` Isaku Yamahata
  0 siblings, 0 replies; 84+ messages in thread
From: Isaku Yamahata @ 2009-10-01  5:40 UTC (permalink / raw)
  To: Aurelien Jarno; +Cc: qemu-devel

On Wed, Sep 30, 2009 at 02:08:24PM +0200, Aurelien Jarno wrote:
> Isaku Yamahata a écrit :
> > This patch set is for Q35 chipset(GMCH and ICH9) based PC.
> 
> Nice work?
> 
> Do you also plan to implement the GMA (integrated graphic card), and the
> IOMMU with this chipset? If not it may be better to call it P35.

No for both GMA and IOMMU at the moment because my current motivation
is pci express.

If there is consensus that it's confusing to call it Q35,
I don't mind to rename P35.
-- 
yamahata

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [Qemu-devel] Re: [PATCH 22/61] pci: use appropriate PRIs in PCI_DPRINTF().
  2009-09-30 11:55   ` [Qemu-devel] " Michael S. Tsirkin
@ 2009-10-01  7:22     ` Isaku Yamahata
  2009-10-01  8:57       ` Michael S. Tsirkin
  0 siblings, 1 reply; 84+ messages in thread
From: Isaku Yamahata @ 2009-10-01  7:22 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel

On Wed, Sep 30, 2009 at 01:55:22PM +0200, Michael S. Tsirkin wrote:
> On Wed, Sep 30, 2009 at 07:17:58PM +0900, Isaku Yamahata wrote:
> > use appropriate PRIs in PCI_DPRINTF() for portability.
> > 
> > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> 
> 
> I'm confused. Shouldn't we be getting 64 bit now?

No. The address below is for PCI configuration space offset which 
remains 32 bit.
The address getting 64 bit is pci bus address.


> 
> > ---
> >  hw/pci.c |   10 ++++++----
> >  1 files changed, 6 insertions(+), 4 deletions(-)
> > 
> > diff --git a/hw/pci.c b/hw/pci.c
> > index 5c59092..4a7568d 100644
> > --- a/hw/pci.c
> > +++ b/hw/pci.c
> > @@ -561,7 +561,7 @@ void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
> >      int config_addr, bus_num;
> >  
> >  #if 0
> > -    PCI_DPRINTF("pci_data_write: addr=%08x val=%08x len=%d\n",
> > +    PCI_DPRINTF("pci_data_write: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
> >                  addr, val, len);
> >  #endif
> >      bus_num = (addr >> 16) & 0xff;
> > @@ -573,7 +573,8 @@ void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
> >      if (!pci_dev)
> >          return;
> >      config_addr = addr & 0xff;
> > -    PCI_DPRINTF("pci_config_write: %s: addr=%02x val=%08x len=%d\n",
> > +    PCI_DPRINTF("pci_config_write: %s: "
> > +                "addr=%02"PRIx32" val=%08"PRI32x" len=%d\n",
> >                  pci_dev->name, config_addr, val, len);
> >      pci_dev->config_write(pci_dev, config_addr, val, len);
> >  }
> > @@ -609,11 +610,12 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
> >      }
> >      config_addr = addr & 0xff;
> >      val = pci_dev->config_read(pci_dev, config_addr, len);
> > -    PCI_DPRINTF("pci_config_read: %s: addr=%02x val=%08x len=%d\n",
> > +    PCI_DPRINTF("pci_config_read: %s: "
> > +                "addr=%02"PRIx32" val=%08"PRIx32" len=%d\n",
> >                  pci_dev->name, config_addr, val, len);
> >   the_end:
> >  #if 0
> > -    PCI_DPRINTF("pci_data_read: addr=%08x val=%08x len=%d\n",
> > +    PCI_DPRINTF("pci_data_read: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
> >                  addr, val, len);
> >  #endif
> >      return val;
> 

-- 
yamahata

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [Qemu-devel] [PATCH 61/61] pc_q35: apic mode for pci interrupt routing.
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 61/61] pc_q35: apic mode for pci interrupt routing Isaku Yamahata
@ 2009-10-01  8:50   ` Avi Kivity
  2009-10-01 16:33     ` Avi Kivity
  0 siblings, 1 reply; 84+ messages in thread
From: Avi Kivity @ 2009-10-01  8:50 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On 09/30/2009 12:18 PM, Isaku Yamahata wrote:
> apic mode for pci interrupt routing.
>
> +static void ich9_lpc_ioapic_update_fn(void *opaque, int reset)
> +{
> +    struct ICH9_LPCIrqState *irq_state = opaque;
> +    struct ICH9_LPCState *ich9_lpc = irq_state->lpc;
> +
> +    /* this can be called via gmch_init() where ich9_lpc isn't
> +       allocated yet */
> +    if (ich9_lpc == NULL)
> +        return;
> +
> +    if (reset)
> +        ich9_lpc->apic_mode = 0;
> +    else
> +        ich9_lpc->apic_mode = 1;
> +}
> +
>    


My understanding was that the OS calls ACPI to set APIC mode.  The ACPI 
routine (_PIC) can then access a register to re-program the interrupt 
router.

Does this reflect how Q35 works, or is this a shortcut?

On my desktop, I have:

     Name (\GPIC, Zero)
     Method (\_PIC, 1, NotSerialized)
     {
         Store (Arg0, \GPIC)
     }

With GPIC later referenced by the various interrupt management routines 
like _PRT; if GPIC is set they return interrupts in the range 16-19, 
otherwise LNKA-LNKD.


-- 
Do not meddle in the internals of kernels, for they are subtle and quick to panic.

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [Qemu-devel] [PATCH 59/61] ioapic: make irr accept more than 32 pins.
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 59/61] ioapic: make irr accept more than 32 pins Isaku Yamahata
@ 2009-10-01  8:52   ` Avi Kivity
  0 siblings, 0 replies; 84+ messages in thread
From: Avi Kivity @ 2009-10-01  8:52 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On 09/30/2009 12:18 PM, Isaku Yamahata wrote:
> make irr accept more than 32 pins.
>    


Is this needed?  I see you later define

+#define ICH9_LPC_IOAPIC_NUM_PINS                24



-- 
Do not meddle in the internals of kernels, for they are subtle and quick to panic.

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [Qemu-devel] Re: [PATCH 22/61] pci: use appropriate PRIs in PCI_DPRINTF().
  2009-10-01  7:22     ` Isaku Yamahata
@ 2009-10-01  8:57       ` Michael S. Tsirkin
  0 siblings, 0 replies; 84+ messages in thread
From: Michael S. Tsirkin @ 2009-10-01  8:57 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Thu, Oct 01, 2009 at 04:22:03PM +0900, Isaku Yamahata wrote:
> On Wed, Sep 30, 2009 at 01:55:22PM +0200, Michael S. Tsirkin wrote:
> > On Wed, Sep 30, 2009 at 07:17:58PM +0900, Isaku Yamahata wrote:
> > > use appropriate PRIs in PCI_DPRINTF() for portability.
> > > 
> > > Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> > 
> > 
> > I'm confused. Shouldn't we be getting 64 bit now?
> 
> No. The address below is for PCI configuration space offset which 
> remains 32 bit.
> The address getting 64 bit is pci bus address.

They aren't really 32 bit either. Any number width will do.
So I wonder: can we change this to unsigned and get rid of the PRI horror?

> > 
> > > ---
> > >  hw/pci.c |   10 ++++++----
> > >  1 files changed, 6 insertions(+), 4 deletions(-)
> > > 
> > > diff --git a/hw/pci.c b/hw/pci.c
> > > index 5c59092..4a7568d 100644
> > > --- a/hw/pci.c
> > > +++ b/hw/pci.c
> > > @@ -561,7 +561,7 @@ void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
> > >      int config_addr, bus_num;
> > >  
> > >  #if 0
> > > -    PCI_DPRINTF("pci_data_write: addr=%08x val=%08x len=%d\n",
> > > +    PCI_DPRINTF("pci_data_write: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
> > >                  addr, val, len);
> > >  #endif
> > >      bus_num = (addr >> 16) & 0xff;
> > > @@ -573,7 +573,8 @@ void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
> > >      if (!pci_dev)
> > >          return;
> > >      config_addr = addr & 0xff;
> > > -    PCI_DPRINTF("pci_config_write: %s: addr=%02x val=%08x len=%d\n",
> > > +    PCI_DPRINTF("pci_config_write: %s: "
> > > +                "addr=%02"PRIx32" val=%08"PRI32x" len=%d\n",
> > >                  pci_dev->name, config_addr, val, len);
> > >      pci_dev->config_write(pci_dev, config_addr, val, len);
> > >  }
> > > @@ -609,11 +610,12 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
> > >      }
> > >      config_addr = addr & 0xff;
> > >      val = pci_dev->config_read(pci_dev, config_addr, len);
> > > -    PCI_DPRINTF("pci_config_read: %s: addr=%02x val=%08x len=%d\n",
> > > +    PCI_DPRINTF("pci_config_read: %s: "
> > > +                "addr=%02"PRIx32" val=%08"PRIx32" len=%d\n",
> > >                  pci_dev->name, config_addr, val, len);
> > >   the_end:
> > >  #if 0
> > > -    PCI_DPRINTF("pci_data_read: addr=%08x val=%08x len=%d\n",
> > > +    PCI_DPRINTF("pci_data_read: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
> > >                  addr, val, len);
> > >  #endif
> > >      return val;
> > 
> 
> -- 
> yamahata

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [Qemu-devel] [PATCH 57/61] ioapic: add callback when entry is set or ioapic is reset
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 57/61] ioapic: add callback when entry is set or ioapic is reset Isaku Yamahata
@ 2009-10-01 13:37   ` Gleb Natapov
  2009-10-01 16:04     ` Avi Kivity
  0 siblings, 1 reply; 84+ messages in thread
From: Gleb Natapov @ 2009-10-01 13:37 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Wed, Sep 30, 2009 at 07:18:33PM +0900, Isaku Yamahata wrote:
> Add hooks to ioapic.
> This is necessary for pci interrupt routing mode from
> PIC mode to IO APIC mode.
According to my very brief looking at ICH9 spec switching from PIC mode
to IO APIC mode is done separately for each PIRQ by setting bit 7 of
PIRQ[n]_ROUT register to 1. This callback looks completely out of place.

> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
>  hw/ioapic.c |   20 +++++++++++++++++++-
>  hw/pc.h     |    2 ++
>  2 files changed, 21 insertions(+), 1 deletions(-)
> 
> diff --git a/hw/ioapic.c b/hw/ioapic.c
> index a9a8e00..882ca9d 100644
> --- a/hw/ioapic.c
> +++ b/hw/ioapic.c
> @@ -53,8 +53,16 @@ struct IOAPICState {
>  
>      uint32_t irr;
>      uint64_t ioredtbl[IOAPIC_NUM_PINS];
> +    ioapic_update_fn update_fn;
> +    void *opaque;
>  };
>  
> +static void ioapic_callback(IOAPICState *s, int reset)
> +{
> +    if (s->update_fn)
> +        s->update_fn(s->opaque, reset);
> +}
> +
>  static void ioapic_service(IOAPICState *s)
>  {
>      uint8_t i;
> @@ -186,6 +194,7 @@ static void ioapic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t va
>                          s->ioredtbl[index] &= ~0xffffffffULL;
>                          s->ioredtbl[index] |= val;
>                      }
> +                    ioapic_callback(s, 0);
>                      ioapic_service(s);
>                  }
>          }
> @@ -210,6 +219,8 @@ static void ioapic_reset(void *opaque)
>      IOAPICState *s = opaque;
>      int i;
>  
> +    ioapic_callback(s, 1);
> +
>      memset(s, 0, sizeof(*s));
>      for(i = 0; i < IOAPIC_NUM_PINS; i++)
>          s->ioredtbl[i] = 1 << 16; /* mask LVT */
> @@ -227,13 +238,15 @@ static CPUWriteMemoryFunc * const ioapic_mem_write[3] = {
>      ioapic_mem_writel,
>  };
>  
> -qemu_irq *ioapic_init(void)
> +qemu_irq *ioapic_init_with_arg(ioapic_update_fn update_fn, void *opaque)
>  {
>      IOAPICState *s;
>      qemu_irq *irq;
>      int io_memory;
>  
>      s = qemu_mallocz(sizeof(IOAPICState));
> +    s->update_fn = update_fn;
> +    s->opaque = opaque;
>      ioapic_reset(s);
>  
>      io_memory = cpu_register_io_memory(ioapic_mem_read,
> @@ -246,3 +259,8 @@ qemu_irq *ioapic_init(void)
>  
>      return irq;
>  }
> +
> +qemu_irq *ioapic_init(void)
> +{
> +    return ioapic_init_with_arg(NULL, NULL);
> +}
> diff --git a/hw/pc.h b/hw/pc.h
> index 7577956..44eac49 100644
> --- a/hw/pc.h
> +++ b/hw/pc.h
> @@ -52,6 +52,8 @@ int apic_accept_pic_intr(CPUState *env);
>  void apic_deliver_pic_intr(CPUState *env, int level);
>  int apic_get_interrupt(CPUState *env);
>  qemu_irq *ioapic_init(void);
> +typedef void (*ioapic_update_fn)(void *opaque, int reset);
> +qemu_irq *ioapic_init_with_arg(ioapic_update_fn update_fn, void *opaque);
>  void apic_reset_irq_delivered(void);
>  int apic_get_irq_delivered(void);
>  
> -- 
> 1.6.0.2
> 
> 

--
			Gleb.

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [Qemu-devel] [PATCH 57/61] ioapic: add callback when entry is set or ioapic is reset
  2009-10-01 13:37   ` Gleb Natapov
@ 2009-10-01 16:04     ` Avi Kivity
  0 siblings, 0 replies; 84+ messages in thread
From: Avi Kivity @ 2009-10-01 16:04 UTC (permalink / raw)
  To: Gleb Natapov; +Cc: Isaku Yamahata, qemu-devel

On 10/01/2009 03:37 PM, Gleb Natapov wrote:
> On Wed, Sep 30, 2009 at 07:18:33PM +0900, Isaku Yamahata wrote:
>    
>> Add hooks to ioapic.
>> This is necessary for pci interrupt routing mode from
>> PIC mode to IO APIC mode.
>>      
> According to my very brief looking at ICH9 spec switching from PIC mode
> to IO APIC mode is done separately for each PIRQ by setting bit 7 of
> PIRQ[n]_ROUT register to 1. This callback looks completely out of place.
>    

Disassembling the _PIC and _PRT methods of a Q35 machine will probably 
yield how this is done on real hardware.

-- 
Do not meddle in the internals of kernels, for they are subtle and quick to panic.

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [Qemu-devel] [PATCH 61/61] pc_q35: apic mode for pci interrupt routing.
  2009-10-01  8:50   ` Avi Kivity
@ 2009-10-01 16:33     ` Avi Kivity
  0 siblings, 0 replies; 84+ messages in thread
From: Avi Kivity @ 2009-10-01 16:33 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On 10/01/2009 10:50 AM, Avi Kivity wrote:
> On 09/30/2009 12:18 PM, Isaku Yamahata wrote:
>> apic mode for pci interrupt routing.
>>
>> +static void ich9_lpc_ioapic_update_fn(void *opaque, int reset)
>> +{
>> +    struct ICH9_LPCIrqState *irq_state = opaque;
>> +    struct ICH9_LPCState *ich9_lpc = irq_state->lpc;
>> +
>> +    /* this can be called via gmch_init() where ich9_lpc isn't
>> +       allocated yet */
>> +    if (ich9_lpc == NULL)
>> +        return;
>> +
>> +    if (reset)
>> +        ich9_lpc->apic_mode = 0;
>> +    else
>> +        ich9_lpc->apic_mode = 1;
>> +}
>> +
>
>
> My understanding was that the OS calls ACPI to set APIC mode.  The 
> ACPI routine (_PIC) can then access a register to re-program the 
> interrupt router.
>
> Does this reflect how Q35 works, or is this a shortcut?
>
> On my desktop, I have:
>
>     Name (\GPIC, Zero)
>     Method (\_PIC, 1, NotSerialized)
>     {
>         Store (Arg0, \GPIC)
>     }
>
> With GPIC later referenced by the various interrupt management 
> routines like _PRT; if GPIC is set they return interrupts in the range 
> 16-19, otherwise LNKA-LNKD.

A real P35 does the same thing.  I think it's implemented by having the 
interrupt lines go to both the PCI links and the ioapic INTI16-INTI19 
inputs; when APIC mode is selected the pci links will be disabled and 
the ioapic activated.

-- 
Do not meddle in the internals of kernels, for they are subtle and quick to panic.

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [Qemu-devel] Re: [PATCH 53/61] pc q35 based chipset emulator
  2009-09-30 10:18 ` [Qemu-devel] [PATCH 53/61] pc q35 based chipset emulator Isaku Yamahata
@ 2009-10-05 10:30   ` Michael S. Tsirkin
  0 siblings, 0 replies; 84+ messages in thread
From: Michael S. Tsirkin @ 2009-10-05 10:30 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Wed, Sep 30, 2009 at 07:18:29PM +0900, Isaku Yamahata wrote:
> +static void gmch_update_pcixbar(struct GMCH_PCIState *gs)

pcie or pciex is the accepted name for pci express.
pcix is another beast.

^ permalink raw reply	[flat|nested] 84+ messages in thread

end of thread, other threads:[~2009-10-05 10:32 UTC | newest]

Thread overview: 84+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-09-30 10:17 [Qemu-devel] [PATCH 00/61] Q35 chip set and stuff Isaku Yamahata
2009-09-30 10:17 ` [Qemu-devel] [PATCH 01/61] acpi: split out pc smbus routines from acpi.c into pc_smbus.c Isaku Yamahata
2009-09-30 10:17 ` [Qemu-devel] [PATCH 02/61] acpi: split out apm register emulation from acpi.c Isaku Yamahata
2009-09-30 10:17 ` [Qemu-devel] [PATCH 03/61] acpi: add acpi constants from linux header files and use them Isaku Yamahata
2009-09-30 10:17 ` [Qemu-devel] [PATCH 04/61] acpi: split acpi.c into the common part and the piix4 part Isaku Yamahata
2009-09-30 10:17 ` [Qemu-devel] [PATCH 05/61] acpi_piix4: remove unused variable in get_pmsts() Isaku Yamahata
2009-09-30 10:17 ` [Qemu-devel] [PATCH 06/61] pc: fix file stream leak in multiboot loader Isaku Yamahata
2009-09-30 10:17 ` [Qemu-devel] [PATCH 07/61] pc, i440fx: Make smm enable/disable function i440fx independent Isaku Yamahata
2009-09-30 10:17 ` [Qemu-devel] [PATCH 08/61] pc: make an unnecessary global variable, pit, local Isaku Yamahata
2009-09-30 10:17 ` [Qemu-devel] [PATCH 09/61] pc: remove a global variable, floppy_controller Isaku Yamahata
2009-09-30 10:17 ` [Qemu-devel] [PATCH 10/61] pc: remove a global variable, RTCState *rtc_state Isaku Yamahata
2009-09-30 10:17 ` [Qemu-devel] [PATCH 11/61] pc: introduce a function to allocate cpu irq Isaku Yamahata
2009-09-30 10:17 ` [Qemu-devel] [PATCH 12/61] pc: make pc_init1() not refer ferr_irq directly Isaku Yamahata
2009-09-30 10:17 ` [Qemu-devel] [PATCH 13/61] pc: split out cpu initialization from pc_init1() into pc_cpus_init() Isaku Yamahata
2009-09-30 10:17 ` [Qemu-devel] [PATCH 14/61] pc: split out memory allocation from pc_init1() into pc_memory_init() Isaku Yamahata
2009-09-30 10:17 ` [Qemu-devel] [PATCH 15/61] pc: split out vga initialization from pc_init1() into pc_vga_init() Isaku Yamahata
2009-09-30 10:17 ` [Qemu-devel] [PATCH 16/61] pc: split out basic device init from pc_init1() into pc_basic_device_init() Isaku Yamahata
2009-09-30 10:17 ` [Qemu-devel] [PATCH 17/61] pc: split out pci device init from pc_init1() into pc_pci_device_init() Isaku Yamahata
2009-09-30 10:17 ` [Qemu-devel] [PATCH 18/61] pc: split out piix specific part from pc.c into pc_piix.c Isaku Yamahata
2009-09-30 10:17 ` [Qemu-devel] [PATCH 19/61] pc_piix: initialize ioapic before use Isaku Yamahata
2009-09-30 10:17 ` [Qemu-devel] [PATCH 20/61] pci: fix PCI_DPRINTF() wrt variadic macro Isaku Yamahata
2009-09-30 10:17 ` [Qemu-devel] [PATCH 21/61] pci: introduce constant PCI_NUM_PINS for the number of interrupt pins, 4 Isaku Yamahata
2009-09-30 10:17 ` [Qemu-devel] [PATCH 22/61] pci: use appropriate PRIs in PCI_DPRINTF() Isaku Yamahata
2009-09-30 11:55   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-01  7:22     ` Isaku Yamahata
2009-10-01  8:57       ` Michael S. Tsirkin
2009-09-30 10:17 ` [Qemu-devel] [PATCH 23/61] pci: use PCI_SLOT() and PCI_FUNC() Isaku Yamahata
2009-09-30 10:18 ` [Qemu-devel] [PATCH 24/61] pci: define a constant to represent a unmapped bar and use it Isaku Yamahata
2009-09-30 10:18 ` [Qemu-devel] [PATCH 25/61] pci: use uint64_t for bar addr and size instead of uint32_t Isaku Yamahata
2009-09-30 14:55   ` malc
2009-10-01  5:34     ` Isaku Yamahata
2009-09-30 10:18 ` [Qemu-devel] [PATCH 26/61] pci: 64bit bar support Isaku Yamahata
2009-09-30 10:18 ` [Qemu-devel] [PATCH 27/61] pci: clean up of pci_update_mappings() Isaku Yamahata
2009-09-30 10:18 ` [Qemu-devel] [PATCH 28/61] pci: factor out while(bus) bus->next loop logic into pci_find_bus_from() Isaku Yamahata
2009-09-30 10:18 ` [Qemu-devel] [PATCH 29/61] pci: factor out the logic to get pci device from address Isaku Yamahata
2009-09-30 10:18 ` [Qemu-devel] [PATCH 30/61] pci_host.h: split non-inline static function in pci_host.h into pci_host_c.h Isaku Yamahata
2009-09-30 10:18 ` [Qemu-devel] [PATCH 31/61] pci: pcie host and mmcfg support Isaku Yamahata
2009-09-30 10:18 ` [Qemu-devel] [PATCH 32/61] pci: helper functions to access PCIDevice::config Isaku Yamahata
2009-09-30 10:47   ` [Qemu-devel] " Michael S. Tsirkin
2009-09-30 10:18 ` [Qemu-devel] [PATCH 33/61] pci: use the symbolic constant, PCI_ROM_ADDRESS_ENABLE instead of 1 Isaku Yamahata
2009-09-30 10:18 ` [Qemu-devel] [PATCH 34/61] pci: introduce pci_swizzle_map_irq_fn() for interrupt pin swizzle Isaku Yamahata
2009-09-30 10:18 ` [Qemu-devel] [PATCH 35/61] piix_pci: use pci_swizzle_map_irq_fn() Isaku Yamahata
2009-09-30 10:18 ` [Qemu-devel] [PATCH 36/61] pci: use QLIST_ macro instead of direct list manipulation Isaku Yamahata
2009-09-30 11:54   ` [Qemu-devel] " Michael S. Tsirkin
2009-09-30 10:18 ` [Qemu-devel] [PATCH 37/61] pci: add helper function for pci config write function to check address Isaku Yamahata
2009-09-30 11:50   ` [Qemu-devel] " Michael S. Tsirkin
2009-09-30 10:18 ` [Qemu-devel] [PATCH 38/61] pci: fix pci_default_write_config() Isaku Yamahata
2009-09-30 10:44   ` [Qemu-devel] " Michael S. Tsirkin
2009-09-30 11:09     ` Isaku Yamahata
2009-09-30 12:50       ` Michael S. Tsirkin
2009-09-30 10:18 ` [Qemu-devel] [PATCH 39/61] pci: factor out config update logic Isaku Yamahata
2009-09-30 10:18 ` [Qemu-devel] [PATCH 40/61] pci: use qdev to get parent bus with PCIBus Isaku Yamahata
2009-09-30 10:18 ` [Qemu-devel] [PATCH 41/61] pci: make bar update function aware of pci bridge Isaku Yamahata
2009-09-30 10:18 ` [Qemu-devel] [PATCH 42/61] pci/brdige: qdevfy and initialize secondary bus and subordinate bus Isaku Yamahata
2009-09-30 10:18 ` [Qemu-devel] [PATCH 43/61] pci: add helper function to initialize wmask Isaku Yamahata
2009-09-30 10:18 ` [Qemu-devel] [PATCH 44/61] pci: initialize wmask according to pci header type Isaku Yamahata
2009-09-30 10:18 ` [Qemu-devel] [PATCH 45/61] pci/monitor: print out bridge's filtering values and so on Isaku Yamahata
2009-09-30 10:18 ` [Qemu-devel] [PATCH 46/61] pci/bridge: implement intel 82801ba bridge Isaku Yamahata
2009-09-30 10:18 ` [Qemu-devel] [PATCH 47/61] pci.h: add more status constats Isaku Yamahata
2009-09-30 10:18 ` [Qemu-devel] [PATCH 48/61] pci id: add subclass codes for serial device Isaku Yamahata
2009-09-30 10:18 ` [Qemu-devel] [PATCH 49/61] pci hot add: pass opaque argument to callback Isaku Yamahata
2009-09-30 10:18 ` [Qemu-devel] [PATCH 50/61] pci hotadd, acpi_piix4: remove global variables Isaku Yamahata
2009-09-30 10:18 ` [Qemu-devel] [PATCH 51/61] vmstate: add a macro for pointer to struct, VMSTATE_STRUCT_POINTER Isaku Yamahata
2009-09-30 10:18 ` [Qemu-devel] [PATCH 52/61] pci: add a hook to replace default pci bus instead of 0 bus Isaku Yamahata
2009-09-30 10:18 ` [Qemu-devel] [PATCH 53/61] pc q35 based chipset emulator Isaku Yamahata
2009-10-05 10:30   ` [Qemu-devel] " Michael S. Tsirkin
2009-09-30 10:18 ` [Qemu-devel] [PATCH 54/61] pci: add opaque argument to pci_map_irq_fn() Isaku Yamahata
2009-09-30 10:18 ` [Qemu-devel] [PATCH 55/61] ioapic: make ioapic_set_irq() static Isaku Yamahata
2009-09-30 10:18 ` [Qemu-devel] [PATCH 56/61] ioapic: clean up of #ifdef DEBUG_IOAPIC Isaku Yamahata
2009-09-30 10:18 ` [Qemu-devel] [PATCH 57/61] ioapic: add callback when entry is set or ioapic is reset Isaku Yamahata
2009-10-01 13:37   ` Gleb Natapov
2009-10-01 16:04     ` Avi Kivity
2009-09-30 10:18 ` [Qemu-devel] [PATCH 58/61] ioapic: make the number of pins configurable Isaku Yamahata
2009-09-30 10:18 ` [Qemu-devel] [PATCH 59/61] ioapic: make irr accept more than 32 pins Isaku Yamahata
2009-10-01  8:52   ` Avi Kivity
2009-09-30 10:18 ` [Qemu-devel] [PATCH 60/61] pci: add opaque arg to pci_map_irq_fn Isaku Yamahata
2009-09-30 10:18 ` [Qemu-devel] [PATCH 61/61] pc_q35: apic mode for pci interrupt routing Isaku Yamahata
2009-10-01  8:50   ` Avi Kivity
2009-10-01 16:33     ` Avi Kivity
2009-09-30 12:00 ` [Qemu-devel] Re: [PATCH 00/61] Q35 chip set and stuff Michael S. Tsirkin
2009-09-30 12:08 ` [Qemu-devel] " Aurelien Jarno
2009-10-01  5:40   ` Isaku Yamahata
2009-09-30 18:37 ` Blue Swirl
2009-09-30 20:53 ` [Qemu-devel] " Anthony Liguori

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.