[Spice-commits] 14 commits - MAINTAINERS cpus.c exec.c include/exec include/qemu linux-user/mips linux-user/syscall.c memory.c savevm.c target-mips/cpu.h target-mips/machine.c target-mips/op_helper.c target-mips/translate.c

Gerd Hoffmann kraxel at kemper.freedesktop.org
Thu Jun 19 06:35:57 PDT 2014


 MAINTAINERS                  |   10 +++
 cpus.c                       |    2 
 exec.c                       |   40 +++++++++++----
 include/exec/cpu-common.h    |    1 
 include/exec/memory.h        |   20 +++----
 include/qemu/bitops.h        |   12 ++++
 linux-user/mips/target_cpu.h |    2 
 linux-user/syscall.c         |    2 
 memory.c                     |  110 ++++++++++++++++++++++++++-----------------
 savevm.c                     |    2 
 target-mips/cpu.h            |   11 ++--
 target-mips/machine.c        |   16 ++++--
 target-mips/op_helper.c      |   14 +++++
 target-mips/translate.c      |   55 ++++++++++++++++++++-
 14 files changed, 215 insertions(+), 82 deletions(-)

New commits:
commit d279279e2b5cd40dbcc863fb66a695990f304077
Author: Petar Jovanovic <petar.jovanovic at imgtec.com>
Date:   Wed Jun 18 17:48:20 2014 +0200

    target-mips: implement UserLocal Register
    
    From MIPS documentation (Volume III):
    
    UserLocal Register (CP0 Register 4, Select 2)
    Compliance Level: Recommended.
    
    The UserLocal register is a read-write register that is not interpreted by
    the hardware and conditionally readable via the RDHWR instruction.
    
    This register only exists if the Config3-ULRI register field is set.
    
    Privileged software may write this register with arbitrary information and
    make it accessible to unprivileged software via register 29 (ULR) of the
    RDHWR instruction. To do so, bit 29 of the HWREna register must be set to a
    1 to enable unprivileged access to the register.
    
    Signed-off-by: Petar Jovanovic <petar.jovanovic at imgtec.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/linux-user/mips/target_cpu.h b/linux-user/mips/target_cpu.h
index ba8e9eb..19b8855 100644
--- a/linux-user/mips/target_cpu.h
+++ b/linux-user/mips/target_cpu.h
@@ -30,7 +30,7 @@ static inline void cpu_clone_regs(CPUMIPSState *env, target_ulong newsp)
 
 static inline void cpu_set_tls(CPUMIPSState *env, target_ulong newtls)
 {
-    env->tls_value = newtls;
+    env->active_tc.CP0_UserLocal = newtls;
 }
 
 #endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index c134c32..7d74079 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -8702,7 +8702,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #ifdef TARGET_NR_set_thread_area
     case TARGET_NR_set_thread_area:
 #if defined(TARGET_MIPS)
-      ((CPUMIPSState *) cpu_env)->tls_value = arg1;
+      ((CPUMIPSState *) cpu_env)->active_tc.CP0_UserLocal = arg1;
       ret = 0;
       break;
 #elif defined(TARGET_CRIS)
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index a9b2c7a..8b9a92e 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -168,6 +168,7 @@ struct TCState {
     target_ulong CP0_TCSchedule;
     target_ulong CP0_TCScheFBack;
     int32_t CP0_Debug_tcstatus;
+    target_ulong CP0_UserLocal;
 };
 
 typedef struct CPUMIPSState CPUMIPSState;
@@ -362,6 +363,7 @@ struct CPUMIPSState {
     int32_t CP0_Config3;
 #define CP0C3_M    31
 #define CP0C3_ISA_ON_EXC 16
+#define CP0C3_ULRI 13
 #define CP0C3_DSPP 10
 #define CP0C3_LPA  7
 #define CP0C3_VEIC 6
@@ -470,6 +472,8 @@ struct CPUMIPSState {
     /* MIPS DSP resources access. */
 #define MIPS_HFLAG_DSP   0x40000  /* Enable access to MIPS DSP resources. */
 #define MIPS_HFLAG_DSPR2 0x80000  /* Enable access to MIPS DSPR2 resources. */
+    /* Extra flag about HWREna register. */
+#define MIPS_HFLAG_HWRENA_ULR 0x100000 /* ULR bit from HWREna is set. */
     target_ulong btarget;        /* Jump / branch target               */
     target_ulong bcond;          /* Branch condition (if needed)       */
 
@@ -479,8 +483,6 @@ struct CPUMIPSState {
     uint32_t CP0_TCStatus_rw_bitmask; /* Read/write bits in CP0_TCStatus */
     int insn_flags; /* Supported instruction set */
 
-    target_ulong tls_value; /* For usermode emulation */
-
     CPU_COMMON
 
     /* Fields from here on are preserved across CPU reset. */
@@ -523,7 +525,7 @@ void mips_cpu_list (FILE *f, fprintf_function cpu_fprintf);
 extern void cpu_wrdsp(uint32_t rs, uint32_t mask_num, CPUMIPSState *env);
 extern uint32_t cpu_rddsp(uint32_t mask_num, CPUMIPSState *env);
 
-#define CPU_SAVE_VERSION 3
+#define CPU_SAVE_VERSION 4
 
 /* MMU modes definitions. We carefully match the indices with our
    hflags layout. */
@@ -682,7 +684,8 @@ static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, target_ulong *pc,
 {
     *pc = env->active_tc.PC;
     *cs_base = 0;
-    *flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK);
+    *flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK |
+                            MIPS_HFLAG_HWRENA_ULR);
 }
 
 static inline int mips_vpe_active(CPUMIPSState *env)
diff --git a/target-mips/machine.c b/target-mips/machine.c
index 0a07db8..0496faa 100644
--- a/target-mips/machine.c
+++ b/target-mips/machine.c
@@ -25,6 +25,7 @@ static void save_tc(QEMUFile *f, TCState *tc)
     qemu_put_betls(f, &tc->CP0_TCSchedule);
     qemu_put_betls(f, &tc->CP0_TCScheFBack);
     qemu_put_sbe32s(f, &tc->CP0_Debug_tcstatus);
+    qemu_put_betls(f, &tc->CP0_UserLocal);
 }
 
 static void save_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu)
@@ -151,7 +152,7 @@ void cpu_save(QEMUFile *f, void *opaque)
         save_fpu(f, &env->fpus[i]);
 }
 
-static void load_tc(QEMUFile *f, TCState *tc)
+static void load_tc(QEMUFile *f, TCState *tc, int version_id)
 {
     int i;
 
@@ -173,6 +174,9 @@ static void load_tc(QEMUFile *f, TCState *tc)
     qemu_get_betls(f, &tc->CP0_TCSchedule);
     qemu_get_betls(f, &tc->CP0_TCScheFBack);
     qemu_get_sbe32s(f, &tc->CP0_Debug_tcstatus);
+    if (version_id >= 4) {
+        qemu_get_betls(f, &tc->CP0_UserLocal);
+    }
 }
 
 static void load_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu)
@@ -194,11 +198,12 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     MIPSCPU *cpu = mips_env_get_cpu(env);
     int i;
 
-    if (version_id != 3)
+    if (version_id < 3) {
         return -EINVAL;
+    }
 
     /* Load active TC */
-    load_tc(f, &env->active_tc);
+    load_tc(f, &env->active_tc, version_id);
 
     /* Load active FPU */
     load_fpu(f, &env->active_fpu);
@@ -298,8 +303,9 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     qemu_get_sbe32s(f, &env->CP0_DESAVE);
 
     /* Load inactive TC state */
-    for (i = 0; i < MIPS_SHADOW_SET_MAX; i++)
-        load_tc(f, &env->tcs[i]);
+    for (i = 0; i < MIPS_SHADOW_SET_MAX; i++) {
+        load_tc(f, &env->tcs[i], version_id);
+    }
     for (i = 0; i < MIPS_FPU_MAX; i++)
         load_fpu(f, &env->fpus[i]);
 
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 4704216..27651a4 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -1297,7 +1297,19 @@ void helper_mtc0_srsconf4(CPUMIPSState *env, target_ulong arg1)
 
 void helper_mtc0_hwrena(CPUMIPSState *env, target_ulong arg1)
 {
-    env->CP0_HWREna = arg1 & 0x0000000F;
+    uint32_t mask = 0x0000000F;
+
+    if (env->CP0_Config3 & (1 << CP0C3_ULRI)) {
+        mask |= (1 << 29);
+
+        if (arg1 & (1 << 29)) {
+            env->hflags |= MIPS_HFLAG_HWRENA_ULR;
+        } else {
+            env->hflags &= ~MIPS_HFLAG_HWRENA_ULR;
+        }
+    }
+
+    env->CP0_HWREna = arg1 & mask;
 }
 
 void helper_mtc0_count(CPUMIPSState *env, target_ulong arg1)
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 76deb7b..2b3befb 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -1072,6 +1072,7 @@ typedef struct DisasContext {
     uint32_t hflags, saved_hflags;
     int bstate;
     target_ulong btarget;
+    bool ulri;
 } DisasContext;
 
 enum {
@@ -4215,7 +4216,18 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
         case 1:
 //            gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
             rn = "ContextConfig";
+            goto die;
 //            break;
+        case 2:
+            if (ctx->ulri) {
+                tcg_gen_ld32s_tl(arg, cpu_env,
+                                 offsetof(CPUMIPSState,
+                                          active_tc.CP0_UserLocal));
+                rn = "UserLocal";
+            } else {
+                tcg_gen_movi_tl(arg, 0);
+            }
+            break;
         default:
             goto die;
         }
@@ -4802,7 +4814,15 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
         case 1:
 //            gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
             rn = "ContextConfig";
+            goto die;
 //            break;
+        case 2:
+            if (ctx->ulri) {
+                tcg_gen_st_tl(arg, cpu_env,
+                              offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
+                rn = "UserLocal";
+            }
+            break;
         default:
             goto die;
         }
@@ -4862,6 +4882,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
         case 0:
             check_insn(ctx, ISA_MIPS32R2);
             gen_helper_mtc0_hwrena(cpu_env, arg);
+            ctx->bstate = BS_STOP;
             rn = "HWREna";
             break;
         default:
@@ -5406,7 +5427,17 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
         case 1:
 //            gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
             rn = "ContextConfig";
+            goto die;
 //            break;
+        case 2:
+            if (ctx->ulri) {
+                tcg_gen_ld_tl(arg, cpu_env,
+                              offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
+                rn = "UserLocal";
+            } else {
+                tcg_gen_movi_tl(arg, 0);
+            }
+            break;
         default:
             goto die;
         }
@@ -5978,7 +6009,15 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
         case 1:
 //           gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
             rn = "ContextConfig";
+            goto die;
 //           break;
+        case 2:
+            if (ctx->ulri) {
+                tcg_gen_st_tl(arg, cpu_env,
+                              offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
+                rn = "UserLocal";
+            }
+            break;
         default:
             goto die;
         }
@@ -6038,6 +6077,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
         case 0:
             check_insn(ctx, ISA_MIPS32R2);
             gen_helper_mtc0_hwrena(cpu_env, arg);
+            ctx->bstate = BS_STOP;
             rn = "HWREna";
             break;
         default:
@@ -9060,12 +9100,20 @@ static void gen_rdhwr(DisasContext *ctx, int rt, int rd)
         break;
     case 29:
 #if defined(CONFIG_USER_ONLY)
-        tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, tls_value));
+        tcg_gen_ld_tl(t0, cpu_env,
+                      offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
         gen_store_gpr(t0, rt);
         break;
 #else
-        /* XXX: Some CPUs implement this in hardware.
-           Not supported yet. */
+        if ((ctx->hflags & MIPS_HFLAG_CP0) ||
+            (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
+            tcg_gen_ld_tl(t0, cpu_env,
+                          offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
+            gen_store_gpr(t0, rt);
+        } else {
+            generate_exception(ctx, EXCP_RI);
+        }
+        break;
 #endif
     default:            /* Invalid */
         MIPS_INVAL("rdhwr");
@@ -15609,6 +15657,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
     ctx.bstate = BS_NONE;
     /* Restore delay slot state from the tb context.  */
     ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
+    ctx.ulri = env->CP0_Config3 & (1 << CP0C3_ULRI);
     restore_cpu_state(env, &ctx);
 #ifdef CONFIG_USER_ONLY
         ctx.mem_idx = MIPS_HFLAG_UM;
commit 739b7a90754924a0f023e8bb865d247ad0a60311
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sat Dec 21 01:15:21 2013 +0100

    bitops: provide an inline implementation of find_first_bit
    
    find_first_bit has started to be used heavily in TCG code. The current
    implementation based on find_next_bit is not optimal and can't be
    optimized be the compiler if the bit array has a fixed size, which is
    the case most of the time.
    
    This new implementation does not use find_next_bit and is yet small
    enough to be inlined.
    
    Cc: Corentin Chary <corentin.chary at gmail.com>
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/include/qemu/bitops.h b/include/qemu/bitops.h
index 340b1e7..7e2d5c9 100644
--- a/include/qemu/bitops.h
+++ b/include/qemu/bitops.h
@@ -157,7 +157,17 @@ unsigned long find_next_zero_bit(const unsigned long *addr,
 static inline unsigned long find_first_bit(const unsigned long *addr,
                                            unsigned long size)
 {
-    return find_next_bit(addr, size, 0);
+    unsigned long result, tmp;
+
+    for (result = 0; result < size; result += BITS_PER_LONG) {
+        tmp = *addr++;
+        if (tmp) {
+            result += ctzl(tmp);
+            return result < size ? result : size;
+        }
+    }
+    /* Not found */
+    return size;
 }
 
 /**
commit 2edaf21b939eb3b7f058fbc3cb7f7e14d6262486
Merge: 0360fbd ab5b3db
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Jun 18 15:08:38 2014 +0100

    Merge remote-tracking branch 'remotes/bonzini/memory' into staging
    
    * remotes/bonzini/memory:
      memory: Don't call memory_region_update_coalesced_range if nothing changed
      memory: MemoryRegion: rename parent to container
      memory: MemoryRegion: factor out memory region re-adder
      memory: MemoryRegion: factor out subregion add functionality
      qtest: fix qtest_clock_warp() for no deadline case
      exec: dummy_section: Pass address space through.
      memory: Simplify mr_add_subregion() if-else
      memory: Don't update all memory region when ioeventfd changed
      unset RAMBlock idstr when unregister MemoryRegion
      exec: introduce qemu_ram_unset_idstr() to unset RAMBlock idstr
      MAINTAINERS: Add myself as Memory API maintainer
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

commit ab5b3db5d711b290d63e954dc64647dd51cef962
Author: Fam Zheng <famz at redhat.com>
Date:   Fri Jun 13 14:34:41 2014 +0800

    memory: Don't call memory_region_update_coalesced_range if nothing changed
    
    With huge number of PCI devices in the system (for example, 200
    virtio-blk-pci), this unconditional call can slow down emulation of
    irrelevant PCI operations drastically, such as a BAR update on a device
    that has no coalescing region. So avoid it.
    
    Signed-off-by: Fam Zheng <famz at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/memory.c b/memory.c
index 85798b0..4895e25 100644
--- a/memory.c
+++ b/memory.c
@@ -1332,6 +1332,7 @@ void memory_region_add_coalescing(MemoryRegion *mr,
 void memory_region_clear_coalescing(MemoryRegion *mr)
 {
     CoalescedMemoryRange *cmr;
+    bool updated = false;
 
     qemu_flush_coalesced_mmio_buffer();
     mr->flush_coalesced_mmio = false;
@@ -1340,8 +1341,12 @@ void memory_region_clear_coalescing(MemoryRegion *mr)
         cmr = QTAILQ_FIRST(&mr->coalesced);
         QTAILQ_REMOVE(&mr->coalesced, cmr, link);
         g_free(cmr);
+        updated = true;
+    }
+
+    if (updated) {
+        memory_region_update_coalesced_range(mr);
     }
-    memory_region_update_coalesced_range(mr);
 }
 
 void memory_region_set_flush_coalesced(MemoryRegion *mr)
commit feca4ac18b7e0df7cdc6e791a7e98cc303feb890
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Jun 11 11:18:09 2014 +0200

    memory: MemoryRegion: rename parent to container
    
    Avoid confusion with the QOM parent.
    
    Reviewed-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/include/exec/memory.h b/include/exec/memory.h
index 1d55ad9..549ae73 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -135,7 +135,7 @@ struct MemoryRegion {
     const MemoryRegionIOMMUOps *iommu_ops;
     void *opaque;
     struct Object *owner;
-    MemoryRegion *parent;
+    MemoryRegion *container;
     Int128 size;
     hwaddr addr;
     void (*destructor)(MemoryRegion *mr);
@@ -815,11 +815,11 @@ void memory_region_set_enabled(MemoryRegion *mr, bool enabled);
 /*
  * memory_region_set_address: dynamically update the address of a region
  *
- * Dynamically updates the address of a region, relative to its parent.
+ * Dynamically updates the address of a region, relative to its container.
  * May be used on regions are currently part of a memory hierarchy.
  *
  * @mr: the region to be updated
- * @addr: new address, relative to parent region
+ * @addr: new address, relative to container region
  */
 void memory_region_set_address(MemoryRegion *mr, hwaddr addr);
 
@@ -836,16 +836,16 @@ void memory_region_set_alias_offset(MemoryRegion *mr,
                                     hwaddr offset);
 
 /**
- * memory_region_present: checks if an address relative to a @parent
- * translates into #MemoryRegion within @parent
+ * memory_region_present: checks if an address relative to a @container
+ * translates into #MemoryRegion within @container
  *
- * Answer whether a #MemoryRegion within @parent covers the address
+ * Answer whether a #MemoryRegion within @container covers the address
  * @addr.
  *
- * @parent: a #MemoryRegion within which @addr is a relative address
- * @addr: the area within @parent to be searched
+ * @container: a #MemoryRegion within which @addr is a relative address
+ * @addr: the area within @container to be searched
  */
-bool memory_region_present(MemoryRegion *parent, hwaddr addr);
+bool memory_region_present(MemoryRegion *container, hwaddr addr);
 
 /**
  * memory_region_find: translate an address/size relative to a
@@ -866,7 +866,7 @@ bool memory_region_present(MemoryRegion *parent, hwaddr addr);
  * Similarly, the . at offset_within_address_space is relative to the
  * address space that contains both regions, the passed and the
  * returned one.  However, in the special case where the @mr argument
- * has no parent (and thus is the root of the address space), the
+ * has no container (and thus is the root of the address space), the
  * following will hold:
  *    . at offset_within_address_space >= @addr
  *    . at offset_within_address_space + . at size <= @addr + @size
diff --git a/memory.c b/memory.c
index 06a4af7..85798b0 100644
--- a/memory.c
+++ b/memory.c
@@ -485,8 +485,8 @@ static AddressSpace *memory_region_to_address_space(MemoryRegion *mr)
 {
     AddressSpace *as;
 
-    while (mr->parent) {
-        mr = mr->parent;
+    while (mr->container) {
+        mr = mr->container;
     }
     QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
         if (mr == as->root) {
@@ -850,7 +850,7 @@ void memory_region_init(MemoryRegion *mr,
     mr->opaque = NULL;
     mr->owner = owner;
     mr->iommu_ops = NULL;
-    mr->parent = NULL;
+    mr->container = NULL;
     mr->size = int128_make64(size);
     if (size == UINT64_MAX) {
         mr->size = int128_2_64();
@@ -1423,10 +1423,10 @@ void memory_region_del_eventfd(MemoryRegion *mr,
     memory_region_transaction_commit();
 }
 
-static void memory_region_update_parent_subregions(MemoryRegion *subregion)
+static void memory_region_update_container_subregions(MemoryRegion *subregion)
 {
     hwaddr offset = subregion->addr;
-    MemoryRegion *mr = subregion->parent;
+    MemoryRegion *mr = subregion->container;
     MemoryRegion *other;
 
     memory_region_transaction_begin();
@@ -1469,10 +1469,10 @@ static void memory_region_add_subregion_common(MemoryRegion *mr,
                                                hwaddr offset,
                                                MemoryRegion *subregion)
 {
-    assert(!subregion->parent);
-    subregion->parent = mr;
+    assert(!subregion->container);
+    subregion->container = mr;
     subregion->addr = offset;
-    memory_region_update_parent_subregions(subregion);
+    memory_region_update_container_subregions(subregion);
 }
 
 void memory_region_add_subregion(MemoryRegion *mr,
@@ -1498,8 +1498,8 @@ void memory_region_del_subregion(MemoryRegion *mr,
                                  MemoryRegion *subregion)
 {
     memory_region_transaction_begin();
-    assert(subregion->parent == mr);
-    subregion->parent = NULL;
+    assert(subregion->container == mr);
+    subregion->container = NULL;
     QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link);
     memory_region_unref(subregion);
     memory_region_update_pending |= mr->enabled && subregion->enabled;
@@ -1519,14 +1519,14 @@ void memory_region_set_enabled(MemoryRegion *mr, bool enabled)
 
 static void memory_region_readd_subregion(MemoryRegion *mr)
 {
-    MemoryRegion *parent = mr->parent;
+    MemoryRegion *container = mr->container;
 
-    if (parent) {
+    if (container) {
         memory_region_transaction_begin();
         memory_region_ref(mr);
-        memory_region_del_subregion(parent, mr);
-        mr->parent = parent;
-        memory_region_update_parent_subregions(mr);
+        memory_region_del_subregion(container, mr);
+        mr->container = container;
+        memory_region_update_container_subregions(mr);
         memory_region_unref(mr);
         memory_region_transaction_commit();
     }
@@ -1578,10 +1578,10 @@ static FlatRange *flatview_lookup(FlatView *view, AddrRange addr)
                    sizeof(FlatRange), cmp_flatrange_addr);
 }
 
-bool memory_region_present(MemoryRegion *parent, hwaddr addr)
+bool memory_region_present(MemoryRegion *container, hwaddr addr)
 {
-    MemoryRegion *mr = memory_region_find(parent, addr, 1).mr;
-    if (!mr || (mr == parent)) {
+    MemoryRegion *mr = memory_region_find(container, addr, 1).mr;
+    if (!mr || (mr == container)) {
         return false;
     }
     memory_region_unref(mr);
@@ -1599,8 +1599,8 @@ MemoryRegionSection memory_region_find(MemoryRegion *mr,
     FlatRange *fr;
 
     addr += mr->addr;
-    for (root = mr; root->parent; ) {
-        root = root->parent;
+    for (root = mr; root->container; ) {
+        root = root->container;
         addr += root->addr;
     }
 
commit 67891b8a85cd8238b8c55ef438b87146ff3646aa
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Thu Jun 5 23:15:18 2014 -0700

    memory: MemoryRegion: factor out memory region re-adder
    
    memory_region_set_address is mostly just a function that deletes and
    re-adds a memory region. Factor this generic functionality out into a
    re-usable function. This prepares support for further QOMification
    of MemoryRegion.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/memory.c b/memory.c
index 15f63e8..06a4af7 100644
--- a/memory.c
+++ b/memory.c
@@ -1517,21 +1517,27 @@ void memory_region_set_enabled(MemoryRegion *mr, bool enabled)
     memory_region_transaction_commit();
 }
 
-void memory_region_set_address(MemoryRegion *mr, hwaddr addr)
+static void memory_region_readd_subregion(MemoryRegion *mr)
 {
     MemoryRegion *parent = mr->parent;
 
-    if (addr == mr->addr || !parent) {
-        mr->addr = addr;
-        return;
+    if (parent) {
+        memory_region_transaction_begin();
+        memory_region_ref(mr);
+        memory_region_del_subregion(parent, mr);
+        mr->parent = parent;
+        memory_region_update_parent_subregions(mr);
+        memory_region_unref(mr);
+        memory_region_transaction_commit();
     }
+}
 
-    memory_region_transaction_begin();
-    memory_region_ref(mr);
-    memory_region_del_subregion(parent, mr);
-    memory_region_add_subregion_common(parent, addr, mr);
-    memory_region_unref(mr);
-    memory_region_transaction_commit();
+void memory_region_set_address(MemoryRegion *mr, hwaddr addr)
+{
+    if (addr != mr->addr) {
+        mr->addr = addr;
+        memory_region_readd_subregion(mr);
+    }
 }
 
 void memory_region_set_alias_offset(MemoryRegion *mr, hwaddr offset)
commit 0598701a4947ddbc19391e008cf753f8f22f3c25
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Thu Jun 5 23:14:44 2014 -0700

    memory: MemoryRegion: factor out subregion add functionality
    
    Split off the core looping code that actually adds subregions into
    it's own fn. This prepares support for Memory Region qomification
    where setting the MR address or parent via QOM will back onto this more
    minimal function.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    [Rename new function. - Paolo]
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/memory.c b/memory.c
index 3811bd1..15f63e8 100644
--- a/memory.c
+++ b/memory.c
@@ -1423,18 +1423,15 @@ void memory_region_del_eventfd(MemoryRegion *mr,
     memory_region_transaction_commit();
 }
 
-static void memory_region_add_subregion_common(MemoryRegion *mr,
-                                               hwaddr offset,
-                                               MemoryRegion *subregion)
+static void memory_region_update_parent_subregions(MemoryRegion *subregion)
 {
+    hwaddr offset = subregion->addr;
+    MemoryRegion *mr = subregion->parent;
     MemoryRegion *other;
 
     memory_region_transaction_begin();
 
-    assert(!subregion->parent);
     memory_region_ref(subregion);
-    subregion->parent = mr;
-    subregion->addr = offset;
     QTAILQ_FOREACH(other, &mr->subregions, subregions_link) {
         if (subregion->may_overlap || other->may_overlap) {
             continue;
@@ -1468,6 +1465,15 @@ done:
     memory_region_transaction_commit();
 }
 
+static void memory_region_add_subregion_common(MemoryRegion *mr,
+                                               hwaddr offset,
+                                               MemoryRegion *subregion)
+{
+    assert(!subregion->parent);
+    subregion->parent = mr;
+    subregion->addr = offset;
+    memory_region_update_parent_subregions(subregion);
+}
 
 void memory_region_add_subregion(MemoryRegion *mr,
                                  hwaddr offset,
commit c9299e2fe789b085f463b2e4232507f5e77f50b4
Author: Sergey Fedorov <serge.fdrv at gmail.com>
Date:   Tue Jun 10 13:10:28 2014 +0400

    qtest: fix qtest_clock_warp() for no deadline case
    
    Use dedicated qemu_soonest_timeout() instead of MIN().
    
    Signed-off-by: Sergey Fedorov <serge.fdrv at gmail.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/cpus.c b/cpus.c
index dd7ac13..af06dc0 100644
--- a/cpus.c
+++ b/cpus.c
@@ -347,7 +347,7 @@ void qtest_clock_warp(int64_t dest)
     assert(qtest_enabled());
     while (clock < dest) {
         int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
-        int64_t warp = MIN(dest - clock, deadline);
+        int64_t warp = qemu_soonest_timeout(dest - clock, deadline);
         seqlock_write_lock(&timers_state.vm_clock_seqlock);
         qemu_icount_bias += warp;
         seqlock_write_unlock(&timers_state.vm_clock_seqlock);
commit a656e22f0993ca1d84cabf47a33e99f27acc3a28
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Mon Jun 2 19:08:44 2014 -0700

    exec: dummy_section: Pass address space through.
    
    Rather than use the global singleton.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/exec.c b/exec.c
index 6ce989a..c3fbbb3 100644
--- a/exec.c
+++ b/exec.c
@@ -1776,10 +1776,12 @@ static subpage_t *subpage_init(AddressSpace *as, hwaddr base)
     return mmio;
 }
 
-static uint16_t dummy_section(PhysPageMap *map, MemoryRegion *mr)
+static uint16_t dummy_section(PhysPageMap *map, AddressSpace *as,
+                              MemoryRegion *mr)
 {
+    assert(as);
     MemoryRegionSection section = {
-        .address_space = &address_space_memory,
+        .address_space = as,
         .mr = mr,
         .offset_within_address_space = 0,
         .offset_within_region = 0,
@@ -1811,13 +1813,13 @@ static void mem_begin(MemoryListener *listener)
     AddressSpaceDispatch *d = g_new0(AddressSpaceDispatch, 1);
     uint16_t n;
 
-    n = dummy_section(&d->map, &io_mem_unassigned);
+    n = dummy_section(&d->map, as, &io_mem_unassigned);
     assert(n == PHYS_SECTION_UNASSIGNED);
-    n = dummy_section(&d->map, &io_mem_notdirty);
+    n = dummy_section(&d->map, as, &io_mem_notdirty);
     assert(n == PHYS_SECTION_NOTDIRTY);
-    n = dummy_section(&d->map, &io_mem_rom);
+    n = dummy_section(&d->map, as, &io_mem_rom);
     assert(n == PHYS_SECTION_ROM);
-    n = dummy_section(&d->map, &io_mem_watch);
+    n = dummy_section(&d->map, as, &io_mem_watch);
     assert(n == PHYS_SECTION_WATCH);
 
     d->phys_map  = (PhysPageEntry) { .ptr = PHYS_MAP_NODE_NIL, .skip = 1 };
commit 3fb5bf5730b90c08d5d1c027900efae210d9b326
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Mon May 12 01:13:47 2014 -0700

    memory: Simplify mr_add_subregion() if-else
    
    This if else is not needed. The previous call to memory_region_add
    (whether _overlap or not) will always set priority and may_overlap
    to desired values. And its not possible to get here without having
    called memory_region_add_subregion due to the null guard on parent.
    So we can just directly call memory_region_add_subregion_common.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/memory.c b/memory.c
index 829d56d..3811bd1 100644
--- a/memory.c
+++ b/memory.c
@@ -1514,8 +1514,6 @@ void memory_region_set_enabled(MemoryRegion *mr, bool enabled)
 void memory_region_set_address(MemoryRegion *mr, hwaddr addr)
 {
     MemoryRegion *parent = mr->parent;
-    int priority = mr->priority;
-    bool may_overlap = mr->may_overlap;
 
     if (addr == mr->addr || !parent) {
         mr->addr = addr;
@@ -1525,11 +1523,7 @@ void memory_region_set_address(MemoryRegion *mr, hwaddr addr)
     memory_region_transaction_begin();
     memory_region_ref(mr);
     memory_region_del_subregion(parent, mr);
-    if (may_overlap) {
-        memory_region_add_subregion_overlap(parent, addr, mr, priority);
-    } else {
-        memory_region_add_subregion(parent, addr, mr);
-    }
+    memory_region_add_subregion_common(parent, addr, mr);
     memory_region_unref(mr);
     memory_region_transaction_commit();
 }
commit 4dc56152237f61694fa42675a78ffd14a509df98
Author: Gonglei <arei.gonglei at huawei.com>
Date:   Thu May 8 11:47:32 2014 +0800

    memory: Don't update all memory region when ioeventfd changed
    
    memory mappings don't rely on ioeventfds, there is no need
    to destroy and rebuild them when manipulating ioeventfds,
    otherwise it scarifies performance.
    
    according to testing result, each ioeventfd deleing needs
    about 5ms, within which memory mapping rebuilding needs
    about 4ms. With many Nics and vmchannel in a VM doing migrating,
    there can be many ioeventfds deleting which increasing
    downtime remarkably.
    
    Signed-off-by: Gonglei <arei.gonglei at huawei.com>
    Signed-off-by: Herongguang <herongguang.he at huawei.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/memory.c b/memory.c
index 678661e..829d56d 100644
--- a/memory.c
+++ b/memory.c
@@ -28,6 +28,7 @@
 
 static unsigned memory_region_transaction_depth;
 static bool memory_region_update_pending;
+static bool ioeventfd_update_pending;
 static bool global_dirty_log = false;
 
 /* flat_view_mutex is taken around reading as->current_map; the critical
@@ -786,22 +787,34 @@ void memory_region_transaction_begin(void)
     ++memory_region_transaction_depth;
 }
 
+static void memory_region_clear_pending(void)
+{
+    memory_region_update_pending = false;
+    ioeventfd_update_pending = false;
+}
+
 void memory_region_transaction_commit(void)
 {
     AddressSpace *as;
 
     assert(memory_region_transaction_depth);
     --memory_region_transaction_depth;
-    if (!memory_region_transaction_depth && memory_region_update_pending) {
-        memory_region_update_pending = false;
-        MEMORY_LISTENER_CALL_GLOBAL(begin, Forward);
+    if (!memory_region_transaction_depth) {
+        if (memory_region_update_pending) {
+            MEMORY_LISTENER_CALL_GLOBAL(begin, Forward);
 
-        QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
-            address_space_update_topology(as);
-        }
+            QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
+                address_space_update_topology(as);
+            }
 
-        MEMORY_LISTENER_CALL_GLOBAL(commit, Forward);
-    }
+            MEMORY_LISTENER_CALL_GLOBAL(commit, Forward);
+        } else if (ioeventfd_update_pending) {
+            QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
+                address_space_update_ioeventfds(as);
+            }
+        }
+        memory_region_clear_pending();
+   }
 }
 
 static void memory_region_destructor_none(MemoryRegion *mr)
@@ -1373,7 +1386,7 @@ void memory_region_add_eventfd(MemoryRegion *mr,
     memmove(&mr->ioeventfds[i+1], &mr->ioeventfds[i],
             sizeof(*mr->ioeventfds) * (mr->ioeventfd_nb-1 - i));
     mr->ioeventfds[i] = mrfd;
-    memory_region_update_pending |= mr->enabled;
+    ioeventfd_update_pending |= mr->enabled;
     memory_region_transaction_commit();
 }
 
@@ -1406,7 +1419,7 @@ void memory_region_del_eventfd(MemoryRegion *mr,
     --mr->ioeventfd_nb;
     mr->ioeventfds = g_realloc(mr->ioeventfds,
                                   sizeof(*mr->ioeventfds)*mr->ioeventfd_nb + 1);
-    memory_region_update_pending |= mr->enabled;
+    ioeventfd_update_pending |= mr->enabled;
     memory_region_transaction_commit();
 }
 
commit b0e56e0b63f350691b52d3e75e89bb64143fbeff
Author: Hu Tao <hutao at cn.fujitsu.com>
Date:   Wed Apr 2 15:13:27 2014 +0800

    unset RAMBlock idstr when unregister MemoryRegion
    
    Signed-off-by: Hu Tao <hutao at cn.fujitsu.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/savevm.c b/savevm.c
index da8aa24..7b2c410 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1209,7 +1209,7 @@ void vmstate_register_ram(MemoryRegion *mr, DeviceState *dev)
 
 void vmstate_unregister_ram(MemoryRegion *mr, DeviceState *dev)
 {
-    /* Nothing do to while the implementation is in RAMBlock */
+    qemu_ram_unset_idstr(memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK);
 }
 
 void vmstate_register_ram_global(MemoryRegion *mr)
commit 20cfe8810d08c99e3fc37be2a5a3355a3a51d208
Author: Hu Tao <hutao at cn.fujitsu.com>
Date:   Wed Apr 2 15:13:26 2014 +0800

    exec: introduce qemu_ram_unset_idstr() to unset RAMBlock idstr
    
    Signed-off-by: Hu Tao <hutao at cn.fujitsu.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/exec.c b/exec.c
index 4e179a6..6ce989a 100644
--- a/exec.c
+++ b/exec.c
@@ -1201,17 +1201,24 @@ static void qemu_ram_setup_dump(void *addr, ram_addr_t size)
     }
 }
 
-void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev)
+static RAMBlock *find_ram_block(ram_addr_t addr)
 {
-    RAMBlock *new_block, *block;
+    RAMBlock *block;
 
-    new_block = NULL;
     QTAILQ_FOREACH(block, &ram_list.blocks, next) {
         if (block->offset == addr) {
-            new_block = block;
-            break;
+            return block;
         }
     }
+
+    return NULL;
+}
+
+void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev)
+{
+    RAMBlock *new_block = find_ram_block(addr);
+    RAMBlock *block;
+
     assert(new_block);
     assert(!new_block->idstr[0]);
 
@@ -1236,6 +1243,15 @@ void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev)
     qemu_mutex_unlock_ramlist();
 }
 
+void qemu_ram_unset_idstr(ram_addr_t addr)
+{
+    RAMBlock *block = find_ram_block(addr);
+
+    if (block) {
+        memset(block->idstr, 0, sizeof(block->idstr));
+    }
+}
+
 static int memory_try_enable_merging(void *addr, size_t len)
 {
     if (!qemu_opt_get_bool(qemu_get_machine_opts(), "mem-merge", true)) {
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
index a21b65a..89ec640 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -54,6 +54,7 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length);
 /* This should not be used by devices.  */
 MemoryRegion *qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr);
 void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev);
+void qemu_ram_unset_idstr(ram_addr_t addr);
 
 void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf,
                             int len, int is_write);
commit 01a9c03c39debe843aea7f4df18274f18d8c6974
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Apr 29 16:05:53 2014 +0200

    MAINTAINERS: Add myself as Memory API maintainer
    
    I'm not including Avi since he has already removed himself from the
    KVM entry.  I'm not going to commit my patches without review.
    
    Acked-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/MAINTAINERS b/MAINTAINERS
index 51a6f51..d1a3405 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -726,6 +726,16 @@ S: Odd Fixes
 F: gdbstub*
 F: gdb-xml/
 
+Memory API
+M: Paolo Bonzini <pbonzini at redhat.com>
+S: Supported
+F: include/exec/ioport.h
+F: ioport.c
+F: include/exec/memory.h
+F: memory.c
+F: include/exec/memory-internal.h
+F: exec.c
+
 SPICE
 M: Gerd Hoffmann <kraxel at redhat.com>
 S: Supported


More information about the Spice-commits mailing list