We allocate memory for cpu->mvp in mips_cpu_realizefn(), but we
never free it, which causes memory leaks like this:

    Direct leak of 24 byte(s) in 2 object(s) allocated from:
        #0 0x5f9458e61c8d in calloc 
(/home/pm215/qemu/build/san/qemu-mips+0x4d8c8d) (BuildId: 
4153e33b3d08657a71ce2a04a82d0c2954966d9c)
        #1 0x74761891a771 in g_malloc0 
(/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x63771) (BuildId: 
116e142b9b52c8a4dfd403e759e71ab8f95d8bb3)
        #2 0x5f94590687aa in mvp_init 
/home/pm215/qemu/build/san/../../target/mips/cpu-defs.c.inc:1037:16
        #3 0x5f94590687aa in mips_cpu_realizefn 
/home/pm215/qemu/build/san/../../target/mips/cpu.c:489:5
        #4 0x5f9459366a3a in device_set_realized 
/home/pm215/qemu/build/san/../../hw/core/qdev.c:523:13
        #5 0x5f9459380a49 in property_set_bool 
/home/pm215/qemu/build/san/../../qom/object.c:2376:5
        #6 0x5f945937bace in object_property_set 
/home/pm215/qemu/build/san/../../qom/object.c:1450:5
        #7 0x5f945938816c in object_property_set_qobject 
/home/pm215/qemu/build/san/../../qom/qom-qobject.c:28:10
        #8 0x5f94592cc100 in cpu_copy 
/home/pm215/qemu/build/san/../../linux-user/main.c:240:25
        #9 0x5f9459309931 in do_syscall1 
/home/pm215/qemu/build/san/../../linux-user/syscall.c
        #10 0x5f94593058d8 in do_syscall 
/home/pm215/qemu/build/san/../../linux-user/syscall.c:14422:15
        #11 0x5f945905c73e in cpu_loop 
/home/pm215/qemu/build/san/../../linux-user/mips/cpu_loop.c:124:23

for linux-user, where each new guest thread is a new CPU object that
we need to destroy on thread exit.

Add an unrealize method which frees this memory.

Signed-off-by: Peter Maydell <[email protected]>
---
 target/mips/cpu.c | 12 ++++++++++++
 target/mips/cpu.h |  1 +
 2 files changed, 13 insertions(+)

diff --git a/target/mips/cpu.c b/target/mips/cpu.c
index 789ca188b5..0663cda003 100644
--- a/target/mips/cpu.c
+++ b/target/mips/cpu.c
@@ -502,6 +502,16 @@ static void mips_cpu_realizefn(DeviceState *dev, Error 
**errp)
     mcc->parent_realize(dev, errp);
 }
 
+static void mips_cpu_unrealizefn(DeviceState *dev)
+{
+    MIPSCPU *cpu = MIPS_CPU(dev);
+    MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(dev);
+
+    g_free(cpu->mvp);
+
+    mcc->parent_unrealize(dev);
+}
+
 static void mips_cpu_initfn(Object *obj)
 {
     MIPSCPU *cpu = MIPS_CPU(obj);
@@ -606,6 +616,8 @@ static void mips_cpu_class_init(ObjectClass *c, const void 
*data)
     device_class_set_props(dc, mips_cpu_properties);
     device_class_set_parent_realize(dc, mips_cpu_realizefn,
                                     &mcc->parent_realize);
+    device_class_set_parent_unrealize(dc, mips_cpu_unrealizefn,
+                                      &mcc->parent_unrealize);
     resettable_class_set_parent_phases(rc, NULL, mips_cpu_reset_hold, NULL,
                                        &mcc->parent_phases);
 
diff --git a/target/mips/cpu.h b/target/mips/cpu.h
index 8de3178b6d..ca36ca0d6f 100644
--- a/target/mips/cpu.h
+++ b/target/mips/cpu.h
@@ -1225,6 +1225,7 @@ struct MIPSCPUClass {
     CPUClass parent_class;
 
     DeviceRealize parent_realize;
+    DeviceUnrealize parent_unrealize;
     ResettablePhases parent_phases;
     const struct mips_def_t *cpu_def;
 
-- 
2.43.0


Reply via email to