[Spice-commits] 15 commits - Makefile.objs Makefile.target cris-dis.c dis-asm.h disas.c hmp-commands.hx hw/pc_piix.c hw/pci-stub.c hw/pci.c hw/pci.h hw/pcie.c hw/pcie.h hw/pcie_aer.c hw/qdev.c hw/qdev.h hw/xio3130_downstream.c hw/xio3130_upstream.c sysemu.h target-cris/translate.c target-cris/translate_v10.c vl.c

Gerd Hoffmann kraxel at kemper.freedesktop.org
Tue Jan 11 04:01:40 PST 2011


 Makefile.objs               |    4 
 Makefile.target             |    2 
 cris-dis.c                  |    9 +
 dis-asm.h                   |    1 
 disas.c                     |    9 +
 hmp-commands.hx             |   25 ++++
 hw/pc_piix.c                |   12 --
 hw/pci-stub.c               |   50 +++++++++
 hw/pci.c                    |   82 ++++++++++++++--
 hw/pci.h                    |    2 
 hw/pcie.c                   |   11 --
 hw/pcie.h                   |    2 
 hw/pcie_aer.c               |  223 ++++++++++++++++++++++++++++++++++++++++++++
 hw/qdev.c                   |   13 +-
 hw/qdev.h                   |    5 
 hw/xio3130_downstream.c     |    2 
 hw/xio3130_upstream.c       |    3 
 sysemu.h                    |    5 
 target-cris/translate.c     |   41 +++++---
 target-cris/translate_v10.c |   10 +
 vl.c                        |    4 
 21 files changed, 460 insertions(+), 55 deletions(-)

New commits:
commit 05bf441eb69a813d3893174d54faa6afa8c0d39b
Author: Edgar E. Iglesias <edgar at axis.com>
Date:   Mon Jan 10 23:28:08 2011 +0100

    cris: Remove unused orig_flags
    
    Based on a patch by Blue Swirl <blauwirbel at gmail.com>.
    
    Signed-off-by: Edgar E. Iglesias <edgar at axis.com>

diff --git a/target-cris/translate.c b/target-cris/translate.c
index 9e403dc..e09aaa9 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -3185,7 +3185,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
 {
 	uint16_t *gen_opc_end;
    	uint32_t pc_start;
-	unsigned int insn_len, orig_flags;
+	unsigned int insn_len;
 	int j, lj;
 	struct DisasContext ctx;
 	struct DisasContext *dc = &ctx;
@@ -3229,7 +3229,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
 	dc->cc_size_uptodate = -1;
 
 	/* Decode TB flags.  */
-	orig_flags = dc->tb_flags = tb->flags & (S_FLAG | P_FLAG | U_FLAG \
+	dc->tb_flags = tb->flags & (S_FLAG | P_FLAG | U_FLAG \
 					| X_FLAG | PFIX_FLAG);
 	dc->delayed_branch = !!(tb->flags & 7);
 	if (dc->delayed_branch)
commit 5cabc5ccfe180241a9086bd9bcbb1b5de8f3fc72
Author: Edgar E. Iglesias <edgar at axis.com>
Date:   Mon Jan 10 23:24:36 2011 +0100

    cris: Allow more TB chaining for crisv10
    
    Signed-off-by: Edgar E. Iglesias <edgar at axis.com>

diff --git a/target-cris/translate.c b/target-cris/translate.c
index 5184155..9e403dc 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -120,9 +120,10 @@ typedef struct DisasContext {
 	unsigned int tb_flags; /* tb dependent flags.  */
 	int is_jmp;
 
-#define JMP_NOJMP    0
-#define JMP_DIRECT   1
-#define JMP_INDIRECT 2
+#define JMP_NOJMP     0
+#define JMP_DIRECT    1
+#define JMP_DIRECT_CC 2
+#define JMP_INDIRECT  3
 	int jmp; /* 0=nojmp, 1=direct, 2=indirect.  */ 
 	uint32_t jmp_pc;
 
@@ -1127,7 +1128,7 @@ static void gen_tst_cc (DisasContext *dc, TCGv cc, int cond)
 static void cris_store_direct_jmp(DisasContext *dc)
 {
 	/* Store the direct jmp state into the cpu-state.  */
-	if (dc->jmp == JMP_DIRECT) {
+	if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) {
 		tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
 		dc->jmp = JMP_INDIRECT;
 	}
@@ -1139,7 +1140,7 @@ static void cris_prepare_cc_branch (DisasContext *dc,
 	/* This helps us re-schedule the micro-code to insns in delay-slots
 	   before the actual jump.  */
 	dc->delayed_branch = 2;
-	dc->jmp = JMP_DIRECT;
+	dc->jmp = JMP_DIRECT_CC;
 	dc->jmp_pc = dc->pc + offset;
 
 	gen_tst_cc (dc, env_btaken, cond);
@@ -1155,7 +1156,9 @@ static inline void cris_prepare_jmp (DisasContext *dc, unsigned int type)
 	   before the actual jump.  */
 	dc->delayed_branch = 2;
 	dc->jmp = type;
-	tcg_gen_movi_tl(env_btaken, 1);
+	if (type == JMP_INDIRECT) {
+		tcg_gen_movi_tl(env_btaken, 1);
+	}
 }
 
 static void gen_load64(DisasContext *dc, TCGv_i64 dst, TCGv addr)
@@ -3193,10 +3196,13 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
 
 	qemu_log_try_set_file(stderr);
 
-	if (env->pregs[PR_VR] == 32)
+	if (env->pregs[PR_VR] == 32) {
 		dc->decoder = crisv32_decoder;
-	else
+		dc->clear_locked_irq = 0;
+	} else {
 		dc->decoder = crisv10_decoder;
+		dc->clear_locked_irq = 1;
+	}
 
 	/* Odd PC indicates that branch is rexecuting due to exception in the
 	 * delayslot, like in real hw.
@@ -3218,7 +3224,6 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
 	dc->cc_mask = 0;
 	dc->update_cc = 0;
 	dc->clear_prefix = 0;
-	dc->clear_locked_irq = 1;
 
 	cris_update_cc_op(dc, CC_OP_FLAGS, 4);
 	dc->cc_size_uptodate = -1;
@@ -3312,7 +3317,14 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
 				    || (dc->flags_x != (tb->flags & X_FLAG))) {
 					cris_store_direct_jmp(dc);
 				}
-				if (dc->jmp == JMP_DIRECT) {
+
+				if (dc->clear_locked_irq) {
+					dc->clear_locked_irq = 0;
+					t_gen_mov_env_TN(locked_irq,
+							 tcg_const_tl(0));
+				}
+
+				if (dc->jmp == JMP_DIRECT_CC) {
 					int l1;
 
 					l1 = gen_new_label();
@@ -3326,6 +3338,11 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
 					gen_goto_tb(dc, 0, dc->pc);
 					dc->is_jmp = DISAS_TB_JUMP;
 					dc->jmp = JMP_NOJMP;
+				} else if (dc->jmp == JMP_DIRECT) {
+					cris_evaluate_flags(dc);
+					gen_goto_tb(dc, 0, dc->jmp_pc);
+					dc->is_jmp = DISAS_TB_JUMP;
+					dc->jmp = JMP_NOJMP;
 				} else {
 					t_gen_cc_jmp(env_btarget, 
 						     tcg_const_tl(dc->pc));
diff --git a/target-cris/translate_v10.c b/target-cris/translate_v10.c
index 6944827..41db158 100644
--- a/target-cris/translate_v10.c
+++ b/target-cris/translate_v10.c
@@ -1060,15 +1060,15 @@ static unsigned int dec10_ind(DisasContext *dc)
             break;
         case CRISV10_IND_JUMP_M:
             if (dc->src == 15) {
-                LOG_DIS("jump.%d %d r%d r%d\n", size,
+                LOG_DIS("jump.%d %d r%d r%d direct\n", size,
                          dc->opcode, dc->src, dc->dst);
                 imm = ldl_code(dc->pc + 2);
                 if (dc->mode == CRISV10_MODE_AUTOINC)
                     insn_len += size;
 
                 t_gen_mov_preg_TN(dc, dc->dst, tcg_const_tl(dc->pc + insn_len));
-                tcg_gen_movi_tl(env_btarget, imm);
-                cris_prepare_jmp(dc, JMP_INDIRECT);
+                dc->jmp_pc = imm;
+                cris_prepare_jmp(dc, JMP_DIRECT);
                 dc->delayed_branch--; /* v10 has no dslot here.  */
             } else {
                 if (dc->dst == 14) {
@@ -1184,7 +1184,9 @@ static unsigned int crisv10_decoder(DisasContext *dc)
     if (dc->clear_prefix && dc->tb_flags & PFIX_FLAG) {
         dc->tb_flags &= ~PFIX_FLAG;
         tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~PFIX_FLAG);
-        dc->cpustate_changed = 1;
+        if (dc->tb_flags != dc->tb->flags) {
+            dc->cpustate_changed = 1;
+        }
     }
 
     /* CRISv10 locks out interrupts on dslots.  */
commit b09cd072df07c63997cc81b6767f2e145d9496e5
Author: Edgar E. Iglesias <edgar at axis.com>
Date:   Mon Jan 10 22:31:09 2011 +0100

    cris: Support disassembly of crisv10
    
    Signed-off-by: Edgar E. Iglesias <edgar at axis.com>

diff --git a/cris-dis.c b/cris-dis.c
index afd775c..5fa67d9 100644
--- a/cris-dis.c
+++ b/cris-dis.c
@@ -2767,7 +2767,6 @@ print_insn_cris_generic (bfd_vma memaddr,
 }
 
 /* Disassemble, prefixing register names with `$'.  CRIS v0..v10.  */
-#if 0
 static int
 print_insn_cris_with_register_prefix (bfd_vma vma,
 				      disassemble_info *info)
@@ -2777,7 +2776,6 @@ print_insn_cris_with_register_prefix (bfd_vma vma,
     return -1;
   return print_insn_cris_generic (vma, info, true);
 }
-#endif
 /* Disassemble, prefixing register names with `$'.  CRIS v32.  */
 
 static int
@@ -2843,6 +2841,13 @@ print_insn_crisv10_v32_without_register_prefix (bfd_vma vma,
 #endif
 
 int
+print_insn_crisv10 (bfd_vma vma,
+		    disassemble_info *info)
+{
+  return print_insn_cris_with_register_prefix(vma, info);
+}
+
+int
 print_insn_crisv32 (bfd_vma vma,
 		    disassemble_info *info)
 {
diff --git a/dis-asm.h b/dis-asm.h
index 3fb4838..356459c 100644
--- a/dis-asm.h
+++ b/dis-asm.h
@@ -397,6 +397,7 @@ extern int print_insn_tic30		(bfd_vma, disassemble_info*);
 extern int print_insn_ppc		(bfd_vma, disassemble_info*);
 extern int print_insn_s390		(bfd_vma, disassemble_info*);
 extern int print_insn_crisv32           (bfd_vma, disassemble_info*);
+extern int print_insn_crisv10           (bfd_vma, disassemble_info*);
 extern int print_insn_microblaze        (bfd_vma, disassemble_info*);
 extern int print_insn_ia64              (bfd_vma, disassemble_info*);
 
diff --git a/disas.c b/disas.c
index afe331f..dd2db14 100644
--- a/disas.c
+++ b/disas.c
@@ -208,8 +208,13 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
     disasm_info.mach = bfd_mach_alpha;
     print_insn = print_insn_alpha;
 #elif defined(TARGET_CRIS)
-    disasm_info.mach = bfd_mach_cris_v32;
-    print_insn = print_insn_crisv32;
+    if (flags != 32) {
+        disasm_info.mach = bfd_mach_cris_v0_v10;
+        print_insn = print_insn_crisv10;
+    } else {
+        disasm_info.mach = bfd_mach_cris_v32;
+        print_insn = print_insn_crisv32;
+    }
 #elif defined(TARGET_MICROBLAZE)
     disasm_info.mach = bfd_arch_microblaze;
     print_insn = print_insn_microblaze;
commit a7bd621d7a270645fb98426c82a0b251fdbc6000
Merge: 8aaf42e... a6a7005...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Jan 10 10:32:01 2011 -0600

    Merge remote branch 'mst/for_anthony' into staging

commit a6a7005d14b3c32d4864a718fb1cb19c789f58a5
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Mon Dec 27 11:21:38 2010 +0200

    pci: fix migration path for devices behind bridges
    
    The device path used for migration is currently broken for
    for all devices behind a nested bridge.
    
    Replace this by a hierarchical list of slot/function numbers, walking
    the path from root down to device. Add :00 after the domain number
    so that if there are no nested bridges, this is compatible
    with what we have now.
    
    Note: as pointed out by Gleb, using openfirmware paths
    might be cleaner, doing this would break compatibility though,
    and the IDs used are not guest or user visible at all,
    so breaking the compatibility is probably not worth it.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci.c b/hw/pci.c
index 44bb3b9..d0b51b8 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -2014,17 +2014,43 @@ static char *pcibus_get_fw_dev_path(DeviceState *dev)
 
 static char *pcibus_get_dev_path(DeviceState *dev)
 {
-    PCIDevice *d = (PCIDevice *)dev;
-    char path[16];
-
-    snprintf(path, sizeof(path), "%04x:%02x:%02x.%x",
-             pci_find_domain(d->bus),
-             0 /* TODO: need a persistent path for nested buses.
-                * Note: pci_bus_num(d->bus) is not right as it's guest
-                * assigned. */,
-             PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
-
-    return strdup(path);
+    PCIDevice *d = container_of(dev, PCIDevice, qdev);
+    PCIDevice *t;
+    int slot_depth;
+    /* Path format: Domain:00:Slot.Function:Slot.Function....:Slot.Function.
+     * 00 is added here to make this format compatible with
+     * domain:Bus:Slot.Func for systems without nested PCI bridges.
+     * Slot.Function list specifies the slot and function numbers for all
+     * devices on the path from root to the specific device. */
+    int domain_len = strlen("DDDD:00");
+    int slot_len = strlen(":SS.F");
+    int path_len;
+    char *path, *p;
+
+    /* Calculate # of slots on path between device and root. */;
+    slot_depth = 0;
+    for (t = d; t; t = t->bus->parent_dev) {
+        ++slot_depth;
+    }
+
+    path_len = domain_len + slot_len * slot_depth;
+
+    /* Allocate memory, fill in the terminating null byte. */
+    path = malloc(path_len + 1 /* For '\0' */);
+    path[path_len] = '\0';
+
+    /* First field is the domain. */
+    snprintf(path, domain_len, "%04x:00", pci_find_domain(d->bus));
+
+    /* Fill in slot numbers. We walk up from device to root, so need to print
+     * them in the reverse order, last to first. */
+    p = path + path_len;
+    for (t = d; t; t = t->bus->parent_dev) {
+        p -= slot_len;
+        snprintf(p, slot_len, ":%02x.%x", PCI_SLOT(t->devfn), PCI_FUNC(d->devfn));
+    }
+
+    return path;
 }
 
 static int pci_qdev_find_recursive(PCIBus *bus,
commit 2ae63bda50ec864a3e61d375b53c8e453ad50140
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri Dec 24 12:14:14 2010 +0900

    pcie/aer: glue aer error injection into qemu monitor
    
    introduce pcie_aer_inject_error command.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hmp-commands.hx b/hmp-commands.hx
index dd3db36..8d84ddc 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -873,6 +873,31 @@ Hot remove PCI device.
 ETEXI
 
     {
+        .name       = "pcie_aer_inject_error",
+        .args_type  = "advisory_non_fatal:-a,correctable:-c,"
+	              "id:s,error_status:s,"
+	              "header0:i?,header1:i?,header2:i?,header3:i?,"
+	              "prefix0:i?,prefix1:i?,prefix2:i?,prefix3:i?",
+        .params     = "[-a] [-c] id "
+                      "<error_status> [<tlp header> [<tlp header prefix>]]",
+        .help       = "inject pcie aer error\n\t\t\t"
+	              " -a for advisory non fatal error\n\t\t\t"
+	              " -c for correctable error\n\t\t\t"
+                      "<id> = qdev device id\n\t\t\t"
+                      "<error_status> = error string or 32bit\n\t\t\t"
+                      "<tlb header> = 32bit x 4\n\t\t\t"
+                      "<tlb header prefix> = 32bit x 4",
+        .user_print  = pcie_aer_inject_error_print,
+        .mhandler.cmd_new = do_pcie_aer_inejct_error,
+    },
+
+STEXI
+ at item pcie_aer_inject_error
+ at findex pcie_aer_inject_error
+Inject PCIe AER error
+ETEXI
+
+    {
         .name       = "host_net_add",
         .args_type  = "device:s,opts:s?",
         .params     = "tap|user|socket|vde|dump [options]",
diff --git a/hw/pci-stub.c b/hw/pci-stub.c
index 674591d..c5a0aa8 100644
--- a/hw/pci-stub.c
+++ b/hw/pci-stub.c
@@ -18,6 +18,7 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "sysemu.h"
 #include "monitor.h"
 #include "pci.h"
 
@@ -35,3 +36,15 @@ void do_pci_info_print(Monitor *mon, const QObject *data)
 {
     pci_error_message(mon);
 }
+
+int do_pcie_aer_inejct_error(Monitor *mon,
+                             const QDict *qdict, QObject **ret_data)
+{
+    pci_error_message(mon);
+    return -ENOSYS;
+}
+
+void pcie_aer_inject_error_print(Monitor *mon, const QObject *data)
+{
+    pci_error_message(mon);
+}
diff --git a/hw/pcie_aer.c b/hw/pcie_aer.c
index cb97a95..6e653dd 100644
--- a/hw/pcie_aer.c
+++ b/hw/pcie_aer.c
@@ -19,6 +19,8 @@
  */
 
 #include "sysemu.h"
+#include "qemu-objects.h"
+#include "monitor.h"
 #include "pci_bridge.h"
 #include "pcie.h"
 #include "msix.h"
@@ -806,3 +808,224 @@ const VMStateDescription vmstate_pcie_aer_log = {
         VMSTATE_END_OF_LIST()
     }
 };
+
+void pcie_aer_inject_error_print(Monitor *mon, const QObject *data)
+{
+    QDict *qdict;
+    int devfn;
+    assert(qobject_type(data) == QTYPE_QDICT);
+    qdict = qobject_to_qdict(data);
+
+    devfn = (int)qdict_get_int(qdict, "devfn");
+    monitor_printf(mon, "OK id: %s domain: %x, bus: %x devfn: %x.%x\n",
+                   qdict_get_str(qdict, "id"),
+                   (int) qdict_get_int(qdict, "domain"),
+                   (int) qdict_get_int(qdict, "bus"),
+                   PCI_SLOT(devfn), PCI_FUNC(devfn));
+}
+
+typedef struct PCIEAERErrorName {
+    const char *name;
+    uint32_t val;
+    bool correctable;
+} PCIEAERErrorName;
+
+/*
+ * AER error name -> value convertion table
+ * This naming scheme is same to linux aer-injection tool.
+ */
+static const struct PCIEAERErrorName pcie_aer_error_list[] = {
+    {
+        .name = "TRAIN",
+        .val = PCI_ERR_UNC_TRAIN,
+        .correctable = false,
+    }, {
+        .name = "DLP",
+        .val = PCI_ERR_UNC_DLP,
+        .correctable = false,
+    }, {
+        .name = "SDN",
+        .val = PCI_ERR_UNC_SDN,
+        .correctable = false,
+    }, {
+        .name = "POISON_TLP",
+        .val = PCI_ERR_UNC_POISON_TLP,
+        .correctable = false,
+    }, {
+        .name = "FCP",
+        .val = PCI_ERR_UNC_FCP,
+        .correctable = false,
+    }, {
+        .name = "COMP_TIME",
+        .val = PCI_ERR_UNC_COMP_TIME,
+        .correctable = false,
+    }, {
+        .name = "COMP_ABORT",
+        .val = PCI_ERR_UNC_COMP_ABORT,
+        .correctable = false,
+    }, {
+        .name = "UNX_COMP",
+        .val = PCI_ERR_UNC_UNX_COMP,
+        .correctable = false,
+    }, {
+        .name = "RX_OVER",
+        .val = PCI_ERR_UNC_RX_OVER,
+        .correctable = false,
+    }, {
+        .name = "MALF_TLP",
+        .val = PCI_ERR_UNC_MALF_TLP,
+        .correctable = false,
+    }, {
+        .name = "ECRC",
+        .val = PCI_ERR_UNC_ECRC,
+        .correctable = false,
+    }, {
+        .name = "UNSUP",
+        .val = PCI_ERR_UNC_UNSUP,
+        .correctable = false,
+    }, {
+        .name = "ACSV",
+        .val = PCI_ERR_UNC_ACSV,
+        .correctable = false,
+    }, {
+        .name = "INTN",
+        .val = PCI_ERR_UNC_INTN,
+        .correctable = false,
+    }, {
+        .name = "MCBTLP",
+        .val = PCI_ERR_UNC_MCBTLP,
+        .correctable = false,
+    }, {
+        .name = "ATOP_EBLOCKED",
+        .val = PCI_ERR_UNC_ATOP_EBLOCKED,
+        .correctable = false,
+    }, {
+        .name = "TLP_PRF_BLOCKED",
+        .val = PCI_ERR_UNC_TLP_PRF_BLOCKED,
+        .correctable = false,
+    }, {
+        .name = "RCVR",
+        .val = PCI_ERR_COR_RCVR,
+        .correctable = true,
+    }, {
+        .name = "BAD_TLP",
+        .val = PCI_ERR_COR_BAD_TLP,
+        .correctable = true,
+    }, {
+        .name = "BAD_DLLP",
+        .val = PCI_ERR_COR_BAD_DLLP,
+        .correctable = true,
+    }, {
+        .name = "REP_ROLL",
+        .val = PCI_ERR_COR_REP_ROLL,
+        .correctable = true,
+    }, {
+        .name = "REP_TIMER",
+        .val = PCI_ERR_COR_REP_TIMER,
+        .correctable = true,
+    }, {
+        .name = "ADV_NONFATAL",
+        .val = PCI_ERR_COR_ADV_NONFATAL,
+        .correctable = true,
+    }, {
+        .name = "INTERNAL",
+        .val = PCI_ERR_COR_INTERNAL,
+        .correctable = true,
+    }, {
+        .name = "HL_OVERFLOW",
+        .val = PCI_ERR_COR_HL_OVERFLOW,
+        .correctable = true,
+    },
+};
+
+static int pcie_aer_parse_error_string(const char *error_name,
+                                       uint32_t *status, bool *correctable)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(pcie_aer_error_list); i++) {
+        const  PCIEAERErrorName *e = &pcie_aer_error_list[i];
+        if (strcmp(error_name, e->name)) {
+            continue;
+        }
+
+        *status = e->val;
+        *correctable = e->correctable;
+        return 0;
+    }
+    return -EINVAL;
+}
+
+int do_pcie_aer_inejct_error(Monitor *mon,
+                             const QDict *qdict, QObject **ret_data)
+{
+    const char *id = qdict_get_str(qdict, "id");
+    const char *error_name;
+    uint32_t error_status;
+    bool correctable;
+    PCIDevice *dev;
+    PCIEAERErr err;
+    int ret;
+
+    ret = pci_qdev_find_device(id, &dev);
+    if (ret < 0) {
+        monitor_printf(mon,
+                       "id or pci device path is invalid or device not "
+                       "found. %s\n", id);
+        return ret;
+    }
+    if (!pci_is_express(dev)) {
+        monitor_printf(mon, "the device doesn't support pci express. %s\n",
+                       id);
+        return -ENOSYS;
+    }
+
+    error_name = qdict_get_str(qdict, "error_status");
+    if (pcie_aer_parse_error_string(error_name, &error_status, &correctable)) {
+        char *e = NULL;
+        error_status = strtoul(error_name, &e, 0);
+        correctable = !!qdict_get_int(qdict, "correctable");
+        if (!e || *e != '\0') {
+            monitor_printf(mon, "invalid error status value. \"%s\"",
+                           error_name);
+            return -EINVAL;
+        }
+    }
+    err.source_id = (pci_bus_num(dev->bus) << 8) | dev->devfn;
+
+    err.flags = 0;
+    if (correctable) {
+        err.flags |= PCIE_AER_ERR_IS_CORRECTABLE;
+    }
+    if (qdict_get_int(qdict, "advisory_non_fatal")) {
+        err.flags |= PCIE_AER_ERR_MAYBE_ADVISORY;
+    }
+    if (qdict_haskey(qdict, "header0")) {
+        err.flags |= PCIE_AER_ERR_HEADER_VALID;
+    }
+    if (qdict_haskey(qdict, "prefix0")) {
+        err.flags |= PCIE_AER_ERR_TLP_PREFIX_PRESENT;
+    }
+
+    err.header[0] = qdict_get_try_int(qdict, "header0", 0);
+    err.header[1] = qdict_get_try_int(qdict, "header1", 0);
+    err.header[2] = qdict_get_try_int(qdict, "header2", 0);
+    err.header[3] = qdict_get_try_int(qdict, "header3", 0);
+
+    err.prefix[0] = qdict_get_try_int(qdict, "prefix0", 0);
+    err.prefix[1] = qdict_get_try_int(qdict, "prefix1", 0);
+    err.prefix[2] = qdict_get_try_int(qdict, "prefix2", 0);
+    err.prefix[3] = qdict_get_try_int(qdict, "prefix3", 0);
+
+    ret = pcie_aer_inject_error(dev, &err);
+    *ret_data = qobject_from_jsonf("{'id': %s, "
+                                   "'domain': %d, 'bus': %d, 'devfn': %d, "
+                                   "'ret': %d}",
+                                   id,
+                                   pci_find_domain(dev->bus),
+                                   pci_bus_num(dev->bus), dev->devfn,
+                                   ret);
+    assert(*ret_data);
+
+    return 0;
+}
diff --git a/sysemu.h b/sysemu.h
index 38a20a3..4182aac 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -157,6 +157,11 @@ void pci_device_hot_add(Monitor *mon, const QDict *qdict);
 void drive_hot_add(Monitor *mon, const QDict *qdict);
 void do_pci_device_hot_remove(Monitor *mon, const QDict *qdict);
 
+/* pcie aer error injection */
+void pcie_aer_inject_error_print(Monitor *mon, const QObject *data);
+int do_pcie_aer_inejct_error(Monitor *mon,
+                             const QDict *qdict, QObject **ret_data);
+
 /* serial ports */
 
 #define MAX_SERIAL_PORTS 4
commit f3006dd1e60af3765c501a082d621f947d6e5974
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri Dec 24 12:14:13 2010 +0900

    pci: introduce a helper function to convert qdev id to PCIDevice
    
    This patch introduce a helper function to get PCIDevice from qdev id.
    This function will be used later.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci.c b/hw/pci.c
index eb21848..44bb3b9 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -2027,3 +2027,38 @@ static char *pcibus_get_dev_path(DeviceState *dev)
     return strdup(path);
 }
 
+static int pci_qdev_find_recursive(PCIBus *bus,
+                                   const char *id, PCIDevice **pdev)
+{
+    DeviceState *qdev = qdev_find_recursive(&bus->qbus, id);
+    if (!qdev) {
+        return -ENODEV;
+    }
+
+    /* roughly check if given qdev is pci device */
+    if (qdev->info->init == &pci_qdev_init &&
+        qdev->parent_bus->info == &pci_bus_info) {
+        *pdev = DO_UPCAST(PCIDevice, qdev, qdev);
+        return 0;
+    }
+    return -EINVAL;
+}
+
+int pci_qdev_find_device(const char *id, PCIDevice **pdev)
+{
+    struct PCIHostBus *host;
+    int rc = -ENODEV;
+
+    QLIST_FOREACH(host, &host_buses, next) {
+        int tmp = pci_qdev_find_recursive(host->bus, id, pdev);
+        if (!tmp) {
+            rc = 0;
+            break;
+        }
+        if (tmp != -ENODEV) {
+            rc = tmp;
+        }
+    }
+
+    return rc;
+}
diff --git a/hw/pci.h b/hw/pci.h
index 6e80b08..052960e 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -252,6 +252,7 @@ PCIBus *pci_find_root_bus(int domain);
 int pci_find_domain(const PCIBus *bus);
 PCIBus *pci_find_bus(PCIBus *bus, int bus_num);
 PCIDevice *pci_find_device(PCIBus *bus, int bus_num, int slot, int function);
+int pci_qdev_find_device(const char *id, PCIDevice **pdev);
 PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr);
 
 int pci_parse_devaddr(const char *addr, int *domp, int *busp,
commit a2ee6b4fcb3e2f2f5d60211ce0f734c61f8e0e30
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri Dec 24 12:14:12 2010 +0900

    qdev: export qdev_find_recursive() for later use
    
    This patch exports qdev_find_recursive() for later use.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index 4747c67..31eb464 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -548,7 +548,7 @@ static BusState *qbus_find_recursive(BusState *bus, const char *name,
     return NULL;
 }
 
-static DeviceState *qdev_find_recursive(BusState *bus, const char *id)
+DeviceState *qdev_find_recursive(BusState *bus, const char *id)
 {
     DeviceState *dev, *ret;
     BusState *child;
diff --git a/hw/qdev.h b/hw/qdev.h
index 5f5a319..2be775f 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -183,6 +183,8 @@ BusState *qdev_get_parent_bus(DeviceState *dev);
 
 /*** BUS API. ***/
 
+DeviceState *qdev_find_recursive(BusState *bus, const char *id);
+
 /* Returns 0 to walk children, > 0 to skip walk, < 0 to terminate walk. */
 typedef int (qbus_walkerfn)(BusState *bus, void *opaque);
 typedef int (qdev_walkerfn)(DeviceState *dev, void *opaque);
commit b3a29fd5604841dac8bfee1bac35f150cab976fb
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Wed Dec 22 19:54:48 2010 +0900

    build, pci: remove QMP dependency on core PCI code
    
    by introducing pci-stub.c, eliminate QMP dependency on core PCI code
    rquired by query-pci command.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index d6b3d60..c3e52c5 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -169,9 +169,7 @@ hw-obj-y =
 hw-obj-y += vl.o loader.o
 hw-obj-$(CONFIG_VIRTIO) += virtio.o virtio-console.o
 hw-obj-y += fw_cfg.o
-# FIXME: Core PCI code and its direct dependencies are required by the
-# QMP query-pci command.
-hw-obj-y += pci.o pci_bridge.o
+hw-obj-$(CONFIG_PCI) += pci.o pci_bridge.o
 hw-obj-$(CONFIG_PCI) += msix.o msi.o
 hw-obj-$(CONFIG_PCI) += pci_host.o pcie_host.o
 hw-obj-$(CONFIG_PCI) += ioh3420.o xio3130_upstream.o xio3130_downstream.o
diff --git a/Makefile.target b/Makefile.target
index d08f5dd..38582d4 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -1,6 +1,7 @@
 # -*- Mode: makefile -*-
 
 GENERATED_HEADERS = config-target.h
+CONFIG_NO_PCI = $(if $(subst n,,$(CONFIG_PCI)),n,y)
 CONFIG_NO_KVM = $(if $(subst n,,$(CONFIG_KVM)),n,y)
 
 include ../config-host.mak
@@ -188,6 +189,7 @@ ifdef CONFIG_SOFTMMU
 obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o balloon.o
 # virtio has to be here due to weird dependency between PCI and virtio-net.
 # need to fix this properly
+obj-$(CONFIG_NO_PCI) += pci-stub.o
 obj-$(CONFIG_VIRTIO) += virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o
 obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
 obj-y += vhost_net.o
diff --git a/hw/pci-stub.c b/hw/pci-stub.c
new file mode 100644
index 0000000..674591d
--- /dev/null
+++ b/hw/pci-stub.c
@@ -0,0 +1,37 @@
+/*
+ * PCI stubs for plathome that doesn't support pci bus.
+ *
+ * Copyright (c) 2010 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "monitor.h"
+#include "pci.h"
+
+static void pci_error_message(Monitor *mon)
+{
+    monitor_printf(mon, "PCI devices not supported\n");
+}
+
+void do_pci_info(Monitor *mon, QObject **ret_data)
+{
+    pci_error_message(mon);
+}
+
+void do_pci_info_print(Monitor *mon, const QObject *data)
+{
+    pci_error_message(mon);
+}
commit 0ead87c8debaf12bf4e8cf5130e4e7fb83dbf126
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Wed Dec 22 15:14:35 2010 +0900

    pcie: add flr support
    
    Support flr: trigger device reset on flr config write.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci.c b/hw/pci.c
index 0cb4117..eb21848 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -137,7 +137,11 @@ static void pci_update_irq_status(PCIDevice *dev)
     }
 }
 
-static void pci_device_reset(PCIDevice *dev)
+/*
+ * This function is called on #RST and FLR.
+ * FLR if PCI_EXP_DEVCTL_BCR_FLR is set
+ */
+void pci_device_reset(PCIDevice *dev)
 {
     int r;
     /* TODO: call the below unconditionally once all pci devices
diff --git a/hw/pci.h b/hw/pci.h
index 17744dc..6e80b08 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -237,6 +237,7 @@ void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev);
 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);
+void pci_device_reset(PCIDevice *dev);
 void pci_bus_reset(PCIBus *bus);
 
 void pci_bus_set_mem_base(PCIBus *bus, target_phys_addr_t base);
diff --git a/hw/pcie.c b/hw/pcie.c
index d1f0086..6a113a9 100644
--- a/hw/pcie.c
+++ b/hw/pcie.c
@@ -380,10 +380,6 @@ void pcie_cap_root_reset(PCIDevice *dev)
     pci_set_word(dev->config + dev->exp.exp_cap + PCI_EXP_RTCTL, 0);
 }
 
-/*
- * TODO: implement FLR:
- * Right now sets the bit which indicates FLR is supported.
- */
 /* function level reset(FLR) */
 void pcie_cap_flr_init(PCIDevice *dev)
 {
@@ -403,8 +399,11 @@ void pcie_cap_flr_write_config(PCIDevice *dev,
                                uint32_t addr, uint32_t val, int len)
 {
     uint8_t *devctl = dev->config + dev->exp.exp_cap + PCI_EXP_DEVCTL;
-    if (pci_word_test_and_clear_mask(devctl, PCI_EXP_DEVCTL_BCR_FLR)) {
-        /* TODO: implement FLR */
+    if (pci_get_word(devctl) & PCI_EXP_DEVCTL_BCR_FLR) {
+        /* Clear PCI_EXP_DEVCTL_BCR_FLR after invoking the reset handler
+           so the handler can detect FLR by looking at this bit. */
+        pci_device_reset(dev);
+        pci_word_test_and_clear_mask(devctl, PCI_EXP_DEVCTL_BCR_FLR);
     }
 }
 
diff --git a/hw/pcie.h b/hw/pcie.h
index 7baa813..bc909e2 100644
--- a/hw/pcie.h
+++ b/hw/pcie.h
@@ -63,8 +63,6 @@ struct PCIExpressDevice {
     /* Offset of express capability in config space */
     uint8_t exp_cap;
 
-    /* TODO FLR */
-
     /* SLOT */
     unsigned int hpev_intx;     /* INTx for hot plug event (0-3:INT[A-D]#)
                                  * default is 0 = INTA#
diff --git a/hw/xio3130_downstream.c b/hw/xio3130_downstream.c
index 1a2d258..5aa6a6b 100644
--- a/hw/xio3130_downstream.c
+++ b/hw/xio3130_downstream.c
@@ -89,7 +89,7 @@ static int xio3130_downstream_initfn(PCIDevice *d)
     if (rc < 0) {
         goto err_msi;
     }
-    pcie_cap_flr_init(d);       /* TODO: implement FLR */
+    pcie_cap_flr_init(d);
     pcie_cap_deverr_init(d);
     pcie_cap_slot_init(d, s->slot);
     pcie_chassis_create(s->chassis);
diff --git a/hw/xio3130_upstream.c b/hw/xio3130_upstream.c
index 387bf6c..a7640f5 100644
--- a/hw/xio3130_upstream.c
+++ b/hw/xio3130_upstream.c
@@ -85,10 +85,7 @@ static int xio3130_upstream_initfn(PCIDevice *d)
     if (rc < 0) {
         goto err_msi;
     }
-
-    /* TODO: implement FLR */
     pcie_cap_flr_init(d);
-
     pcie_cap_deverr_init(d);
     rc = pcie_aer_init(d, XIO3130_AER_OFFSET);
     if (rc < 0) {
commit 362dd48c16728a656c1ef75f8160838127fd76d5
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Wed Dec 22 15:13:43 2010 +0900

    pc/piix: fix mismerge of b1aeb92666d2fde413c34578b3b42bbfe5f2a506
    
    The change set of b1aeb92666d2fde413c34578b3b42bbfe5f2a506 in pci branch
    was mismerged. The compatibility should be kept for 0.13, not for 0.14.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index a2fb554..f82508d 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -217,14 +217,6 @@ static QEMUMachine pc_machine = {
     .desc = "Standard PC",
     .init = pc_init_pci,
     .max_cpus = 255,
-    .compat_props = (GlobalProperty[]) {
-        {
-            .driver   = "PCI",
-            .property = "command_serr_enable",
-            .value    = "off",
-        },
-        { /* end of list */ }
-    },
     .is_default = 1,
 };
 
@@ -246,6 +238,10 @@ static QEMUMachine pc_machine_v0_13 = {
             .driver   = "vmware-svga",
             .property = "rombar",
             .value    = stringify(0),
+        },{
+            .driver   = "PCI",
+            .property = "command_serr_enable",
+            .value    = "off",
         },
         { /* end of list */ }
     },
commit f530cce3152b55a535e9e87610110fefa4e9c853
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Mon Dec 20 15:17:10 2010 +0200

    qdev: remove an unused function
    
    qbus_reset_all is unused, remove it
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index d93a6c4..4747c67 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -328,15 +328,10 @@ void qdev_reset_all(DeviceState *dev)
     qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
 }
 
-void qbus_reset_all(BusState *bus)
-{
-    qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
-}
-
 void qbus_reset_all_fn(void *opaque)
 {
     BusState *bus = opaque;
-    qbus_reset_all(bus);
+    qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
 }
 
 /* can be used as ->unplug() callback for the simple cases */
diff --git a/hw/qdev.h b/hw/qdev.h
index b239bb4..5f5a319 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -198,7 +198,6 @@ int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
 int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
                        qbus_walkerfn *busfn, void *opaque);
 void qdev_reset_all(DeviceState *dev);
-void qbus_reset_all(BusState *bus);
 void qbus_reset_all_fn(void *opaque);
 
 void qbus_free(BusState *bus);
commit 80376c3fc2c38fdd45354e4b0eb45031f35587ed
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Mon Dec 20 14:33:35 2010 +0900

    qbus: register reset handler for qbus whose parent is NULL
    
    Stefan Weil reported the regression caused by
    ec990eb622ad46df5ddcb1e94c418c271894d416 as follows
    
    > The second regression also occurs with MIPS malta.
    > Networking no longer works with the default pcnet nic.
    >
    > This is caused because the reset function for pcnet is no
    > longer called during system boot. The result in an invalid
    > mac address (all zero) and a non-working nic.
    >
    > For this second regression I still have no simple solution.
    > Of course mips_malta.c should be converted to qdev which
    > would fix both problems (but only for malta system emulation).
    
    The issue is, it is assumed that all qbuses, qdeves are under
    main_system_bus. But there are qbuses whose parent is NULL. So it
    is necessary to trigger reset for those qbuses.
    (On the other hand, if NULL is passed to qdev_create(), its parent bus
    is main_system_bus.)
    Ideally those buses should be moved under bus controller
    device which is qdev. But it's not done yet.
    So register qbus reset handler for qbus whose parent is NULL.
    
    Reported-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: "Michael S. Tsirkin" <mst at redhat.com>
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index 6fc9b02..d93a6c4 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -333,6 +333,12 @@ void qbus_reset_all(BusState *bus)
     qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
 }
 
+void qbus_reset_all_fn(void *opaque)
+{
+    BusState *bus = opaque;
+    qbus_reset_all(bus);
+}
+
 /* can be used as ->unplug() callback for the simple cases */
 int qdev_simple_unplug_cb(DeviceState *dev)
 {
@@ -754,8 +760,11 @@ void qbus_create_inplace(BusState *bus, BusInfo *info,
     if (parent) {
         QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
         parent->num_child_bus++;
+    } else if (bus != main_system_bus) {
+        /* TODO: once all bus devices are qdevified,
+           only reset handler for main_system_bus should be registered here. */
+        qemu_register_reset(qbus_reset_all_fn, bus);
     }
-
 }
 
 BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
@@ -778,6 +787,9 @@ void qbus_free(BusState *bus)
     if (bus->parent) {
         QLIST_REMOVE(bus, sibling);
         bus->parent->num_child_bus--;
+    } else {
+        assert(bus != main_system_bus); /* main_system_bus is never freed */
+        qemu_unregister_reset(qbus_reset_all_fn, bus);
     }
     qemu_free((void*)bus->name);
     if (bus->qdev_allocated) {
diff --git a/hw/qdev.h b/hw/qdev.h
index aaaf55a..b239bb4 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -199,6 +199,8 @@ int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
                        qbus_walkerfn *busfn, void *opaque);
 void qdev_reset_all(DeviceState *dev);
 void qbus_reset_all(BusState *bus);
+void qbus_reset_all_fn(void *opaque);
+
 void qbus_free(BusState *bus);
 
 #define FROM_QBUS(type, dev) DO_UPCAST(type, qbus, dev)
diff --git a/vl.c b/vl.c
index c4d3fc0..8d6bab4 100644
--- a/vl.c
+++ b/vl.c
@@ -3088,7 +3088,9 @@ int main(int argc, char **argv, char **envp)
         exit(1);
     }
 
-    qemu_register_reset((void *)qbus_reset_all, sysbus_get_default());
+    /* TODO: once all bus devices are qdevified, this should be done
+     * when bus is created by qdev.c */
+    qemu_register_reset(qbus_reset_all_fn, sysbus_get_default());
     qemu_run_machine_init_done_notifiers();
 
     qemu_system_reset();
commit 68694897e55ebd229898d4b6546877ccea500954
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Thu Dec 16 19:33:22 2010 +0100

    qdev: sysbus_get_default must not return a NULL pointer (fix regression)
    
    Every system should have some sort of main system bus,
    so sysbus_get_default should always return a valid bus.
    
    Without this patch, at least mipssim and malta no longer
    start but raise a null pointer access exception (caused by
    commit ec990eb622ad46df5ddcb1e94c418c271894d416).
    
    Cc: Anthony Liguori <anthony at codemonkey.ws>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index 10e28df..6fc9b02 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -107,10 +107,7 @@ DeviceState *qdev_create(BusState *bus, const char *name)
     DeviceInfo *info;
 
     if (!bus) {
-        if (!main_system_bus) {
-            main_system_bus = qbus_create(&system_bus_info, NULL, "main-system-bus");
-        }
-        bus = main_system_bus;
+        bus = sysbus_get_default();
     }
 
     info = qdev_find_info(bus->info, name);
@@ -311,6 +308,10 @@ static int qdev_reset_one(DeviceState *dev, void *opaque)
 
 BusState *sysbus_get_default(void)
 {
+    if (!main_system_bus) {
+        main_system_bus = qbus_create(&system_bus_info, NULL,
+                                      "main-system-bus");
+    }
     return main_system_bus;
 }
 
commit af0669f0edbbcb8c17f7c2b919089485c8327f4f
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Tue Dec 14 14:24:53 2010 +0200

    pci: don't use bus number in migration, stub out
    
    Using bus numbers in migration is clearly wrong as
    they are guest assigned. Not really sure what the
    right thing to do is, for now stick 0 in there so things
    keep working for non-nested setups, add a TODO.
    
    We also probably have to mark nested bridges as non-migrateable
    until this is fixed?
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    Acked-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/hw/pci.c b/hw/pci.c
index ef00d20..0cb4117 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -2014,7 +2014,10 @@ static char *pcibus_get_dev_path(DeviceState *dev)
     char path[16];
 
     snprintf(path, sizeof(path), "%04x:%02x:%02x.%x",
-             pci_find_domain(d->bus), d->config[PCI_SECONDARY_BUS],
+             pci_find_domain(d->bus),
+             0 /* TODO: need a persistent path for nested buses.
+                * Note: pci_bus_num(d->bus) is not right as it's guest
+                * assigned. */,
              PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
 
     return strdup(path);


More information about the Spice-commits mailing list