diff mbox

[v2] pc-dimm/numa: Fix stat of memory size in node when hotplug memory

Message ID 1411042028-14288-1-git-send-email-zhang.zhanghailiang@huawei.com
State New
Headers show

Commit Message

Zhanghailiang Sept. 18, 2014, 12:07 p.m. UTC
When do memory hotplug, if there is numa node, we should add
the memory size to the corresponding node memory size.

For now, it mainly affects the result of hmp command "info numa".

Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
---
 v2:
- Don't modify the numa_info.node_mem directly when treating hotplug memory,
  fix the "info numa" instead (suggested by Igor Mammedov)
---
 hw/mem/pc-dimm.c         | 27 +++++++++++++++++++++++++++
 include/hw/mem/pc-dimm.h |  2 ++
 include/sysemu/sysemu.h  |  1 +
 monitor.c                |  6 +++++-
 numa.c                   | 15 +++++++++++++++
 5 files changed, 50 insertions(+), 1 deletion(-)

Comments

chenfan Sept. 19, 2014, 1:43 a.m. UTC | #1
On Thu, 2014-09-18 at 20:07 +0800, zhanghailiang wrote: 
> When do memory hotplug, if there is numa node, we should add
> the memory size to the corresponding node memory size.
> 
> For now, it mainly affects the result of hmp command "info numa".
> 
> Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
> ---
>  v2:
> - Don't modify the numa_info.node_mem directly when treating hotplug memory,
>   fix the "info numa" instead (suggested by Igor Mammedov)
> ---
>  hw/mem/pc-dimm.c         | 27 +++++++++++++++++++++++++++
>  include/hw/mem/pc-dimm.h |  2 ++
>  include/sysemu/sysemu.h  |  1 +
>  monitor.c                |  6 +++++-
>  numa.c                   | 15 +++++++++++++++
>  5 files changed, 50 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
> index 5bfc5b7..7b233a6 100644
> --- a/hw/mem/pc-dimm.c
> +++ b/hw/mem/pc-dimm.c
> @@ -195,6 +195,33 @@ out:
>      return ret;
>  }
>  
> +static int pc_dimm_stat_mem_size(Object *obj, void *opaque)
> +{
> +    uint64_t *node_mem = opaque;
> +    int ret;
> +
> +    if (object_dynamic_cast(obj, TYPE_PC_DIMM)) {
> +        DeviceState *dev = DEVICE(obj);
> +        if (dev->realized && dev->hotplugged) {
> +            PCDIMMDevice *dimm = PC_DIMM(obj);
> +            int size = object_property_get_int(OBJECT(dimm), PC_DIMM_SIZE_PROP,
> +                                               NULL);
> +            if (size < 0) {
> +                return -1;
> +            }
> +            node_mem[dimm->node] += size;
> +        }
> +    }
> +
> +    ret = object_child_foreach(obj, pc_dimm_stat_mem_size, opaque);
> +    return ret;
> +}
> +
> +void pc_dimm_stat_node_mem(uint64_t *node_mem)
> +{
> +    object_child_foreach(qdev_get_machine(), pc_dimm_stat_mem_size, node_mem);
> +}
> +
>  static Property pc_dimm_properties[] = {
>      DEFINE_PROP_UINT64(PC_DIMM_ADDR_PROP, PCDIMMDevice, addr, 0),
>      DEFINE_PROP_UINT32(PC_DIMM_NODE_PROP, PCDIMMDevice, node, 0),
> diff --git a/include/hw/mem/pc-dimm.h b/include/hw/mem/pc-dimm.h
> index 761eeef..0c9a8eb 100644
> --- a/include/hw/mem/pc-dimm.h
> +++ b/include/hw/mem/pc-dimm.h
> @@ -78,4 +78,6 @@ uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
>  int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp);
>  
>  int qmp_pc_dimm_device_list(Object *obj, void *opaque);
> +
> +void pc_dimm_stat_node_mem(uint64_t *node_mem);
>  #endif
> diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
> index d8539fd..cfc1592 100644
> --- a/include/sysemu/sysemu.h
> +++ b/include/sysemu/sysemu.h
> @@ -160,6 +160,7 @@ typedef struct node_info {
>  extern NodeInfo numa_info[MAX_NODES];
>  void set_numa_nodes(void);
>  void set_numa_modes(void);
> +int query_numa_node_mem(uint64_t *node_mem);
>  extern QemuOptsList qemu_numa_opts;
>  int numa_init_func(QemuOpts *opts, void *opaque);
>  
> diff --git a/monitor.c b/monitor.c
> index 7467521..c8c812f 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -1948,7 +1948,10 @@ static void do_info_numa(Monitor *mon, const QDict *qdict)
>  {
>      int i;
>      CPUState *cpu;
> +    uint64_t *node_mem;
>  
> +    node_mem = g_new0(uint64_t, nb_numa_nodes);
> +    query_numa_node_mem(node_mem);
>      monitor_printf(mon, "%d nodes\n", nb_numa_nodes);
>      for (i = 0; i < nb_numa_nodes; i++) {
>          monitor_printf(mon, "node %d cpus:", i);
> @@ -1959,8 +1962,9 @@ static void do_info_numa(Monitor *mon, const QDict *qdict)
>          }
>          monitor_printf(mon, "\n");
>          monitor_printf(mon, "node %d size: %" PRId64 " MB\n", i,
> -            numa_info[i].node_mem >> 20);
> +            node_mem[i] >> 20);
the indentation looks weird.

>      }
> +    g_free(node_mem);
>  }
>  
>  #ifdef CONFIG_PROFILER
> diff --git a/numa.c b/numa.c
> index 3b98135..4e27dd8 100644
> --- a/numa.c
> +++ b/numa.c
> @@ -35,6 +35,7 @@
>  #include "hw/boards.h"
>  #include "sysemu/hostmem.h"
>  #include "qmp-commands.h"
> +#include "hw/mem/pc-dimm.h"
>  
>  QemuOptsList qemu_numa_opts = {
>      .name = "numa",
> @@ -315,6 +316,20 @@ void memory_region_allocate_system_memory(MemoryRegion *mr, Object *owner,
>      }
>  }
>  
> +int query_numa_node_mem(uint64_t *node_mem)
> +{
> +    int i;
> +
> +    if (nb_numa_nodes <= 0) {
> +        return 0;
if you don't change the out parameter node_mem, node_mem should
initialization.



Regards,
Chen 

> +    }
> +    pc_dimm_stat_node_mem(node_mem);
> +    for (i = 0; i < nb_numa_nodes; i++) {
> +        node_mem[i] += numa_info[i].node_mem;
> +    }
> +    return 0;
> +}
> +
>  static int query_memdev(Object *obj, void *opaque)
>  {
>      MemdevList **list = opaque;
Zhanghailiang Sept. 19, 2014, 3:55 a.m. UTC | #2
On 2014/9/19 9:43, Chen, Fan wrote:
> On Thu, 2014-09-18 at 20:07 +0800, zhanghailiang wrote:
>> When do memory hotplug, if there is numa node, we should add
>> the memory size to the corresponding node memory size.
>>
>> For now, it mainly affects the result of hmp command "info numa".
>>
>> Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
>> ---
>>   v2:
>> - Don't modify the numa_info.node_mem directly when treating hotplug memory,
>>    fix the "info numa" instead (suggested by Igor Mammedov)
>> ---
>>   hw/mem/pc-dimm.c         | 27 +++++++++++++++++++++++++++
>>   include/hw/mem/pc-dimm.h |  2 ++
>>   include/sysemu/sysemu.h  |  1 +
>>   monitor.c                |  6 +++++-
>>   numa.c                   | 15 +++++++++++++++
>>   5 files changed, 50 insertions(+), 1 deletion(-)
>>
>> diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
>> index 5bfc5b7..7b233a6 100644
>> --- a/hw/mem/pc-dimm.c
>> +++ b/hw/mem/pc-dimm.c
>> @@ -195,6 +195,33 @@ out:
>>       return ret;
>>   }
>>
>> +static int pc_dimm_stat_mem_size(Object *obj, void *opaque)
>> +{
>> +    uint64_t *node_mem = opaque;
>> +    int ret;
>> +
>> +    if (object_dynamic_cast(obj, TYPE_PC_DIMM)) {
>> +        DeviceState *dev = DEVICE(obj);
>> +        if (dev->realized && dev->hotplugged) {
>> +            PCDIMMDevice *dimm = PC_DIMM(obj);
>> +            int size = object_property_get_int(OBJECT(dimm), PC_DIMM_SIZE_PROP,
>> +                                               NULL);
>> +            if (size < 0) {
>> +                return -1;
>> +            }
>> +            node_mem[dimm->node] += size;
>> +        }
>> +    }
>> +
>> +    ret = object_child_foreach(obj, pc_dimm_stat_mem_size, opaque);
>> +    return ret;
>> +}
>> +
>> +void pc_dimm_stat_node_mem(uint64_t *node_mem)
>> +{
>> +    object_child_foreach(qdev_get_machine(), pc_dimm_stat_mem_size, node_mem);
>> +}
>> +
>>   static Property pc_dimm_properties[] = {
>>       DEFINE_PROP_UINT64(PC_DIMM_ADDR_PROP, PCDIMMDevice, addr, 0),
>>       DEFINE_PROP_UINT32(PC_DIMM_NODE_PROP, PCDIMMDevice, node, 0),
>> diff --git a/include/hw/mem/pc-dimm.h b/include/hw/mem/pc-dimm.h
>> index 761eeef..0c9a8eb 100644
>> --- a/include/hw/mem/pc-dimm.h
>> +++ b/include/hw/mem/pc-dimm.h
>> @@ -78,4 +78,6 @@ uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
>>   int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp);
>>
>>   int qmp_pc_dimm_device_list(Object *obj, void *opaque);
>> +
>> +void pc_dimm_stat_node_mem(uint64_t *node_mem);
>>   #endif
>> diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
>> index d8539fd..cfc1592 100644
>> --- a/include/sysemu/sysemu.h
>> +++ b/include/sysemu/sysemu.h
>> @@ -160,6 +160,7 @@ typedef struct node_info {
>>   extern NodeInfo numa_info[MAX_NODES];
>>   void set_numa_nodes(void);
>>   void set_numa_modes(void);
>> +int query_numa_node_mem(uint64_t *node_mem);
>>   extern QemuOptsList qemu_numa_opts;
>>   int numa_init_func(QemuOpts *opts, void *opaque);
>>
>> diff --git a/monitor.c b/monitor.c
>> index 7467521..c8c812f 100644
>> --- a/monitor.c
>> +++ b/monitor.c
>> @@ -1948,7 +1948,10 @@ static void do_info_numa(Monitor *mon, const QDict *qdict)
>>   {
>>       int i;
>>       CPUState *cpu;
>> +    uint64_t *node_mem;
>>
>> +    node_mem = g_new0(uint64_t, nb_numa_nodes);
>> +    query_numa_node_mem(node_mem);
>>       monitor_printf(mon, "%d nodes\n", nb_numa_nodes);
>>       for (i = 0; i < nb_numa_nodes; i++) {
>>           monitor_printf(mon, "node %d cpus:", i);
>> @@ -1959,8 +1962,9 @@ static void do_info_numa(Monitor *mon, const QDict *qdict)
>>           }
>>           monitor_printf(mon, "\n");
>>           monitor_printf(mon, "node %d size: %" PRId64 " MB\n", i,
>> -            numa_info[i].node_mem >> 20);
>> +            node_mem[i] >> 20);
> the indentation looks weird.
>

Will fix this, Thanks;)

>>       }
>> +    g_free(node_mem);
>>   }
>>
>>   #ifdef CONFIG_PROFILER
>> diff --git a/numa.c b/numa.c
>> index 3b98135..4e27dd8 100644
>> --- a/numa.c
>> +++ b/numa.c
>> @@ -35,6 +35,7 @@
>>   #include "hw/boards.h"
>>   #include "sysemu/hostmem.h"
>>   #include "qmp-commands.h"
>> +#include "hw/mem/pc-dimm.h"
>>
>>   QemuOptsList qemu_numa_opts = {
>>       .name = "numa",
>> @@ -315,6 +316,20 @@ void memory_region_allocate_system_memory(MemoryRegion *mr, Object *owner,
>>       }
>>   }
>>
>> +int query_numa_node_mem(uint64_t *node_mem)
>> +{
>> +    int i;
>> +
>> +    if (nb_numa_nodes <= 0) {
>> +        return 0;
> if you don't change the out parameter node_mem, node_mem should
> initialization.
>

Actually, node_mem has been initialized in do_info_numa where it is allocated.:)

Thanks,
zhanghailiang

>
> Regards,
> Chen
>
>> +    }
>> +    pc_dimm_stat_node_mem(node_mem);
>> +    for (i = 0; i < nb_numa_nodes; i++) {
>> +        node_mem[i] += numa_info[i].node_mem;
>> +    }
>> +    return 0;
>> +}
>> +
>>   static int query_memdev(Object *obj, void *opaque)
>>   {
>>       MemdevList **list = opaque;
>
Igor Mammedov Sept. 19, 2014, 1:51 p.m. UTC | #3
On Thu, 18 Sep 2014 20:07:08 +0800
zhanghailiang <zhang.zhanghailiang@huawei.com> wrote:

> When do memory hotplug, if there is numa node, we should add
> the memory size to the corresponding node memory size.
> 
> For now, it mainly affects the result of hmp command "info numa".
> 
> Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
> ---
>  v2:
> - Don't modify the numa_info.node_mem directly when treating hotplug memory,
>   fix the "info numa" instead (suggested by Igor Mammedov)
> ---
>  hw/mem/pc-dimm.c         | 27 +++++++++++++++++++++++++++
>  include/hw/mem/pc-dimm.h |  2 ++
>  include/sysemu/sysemu.h  |  1 +
>  monitor.c                |  6 +++++-
>  numa.c                   | 15 +++++++++++++++
>  5 files changed, 50 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
> index 5bfc5b7..7b233a6 100644
> --- a/hw/mem/pc-dimm.c
> +++ b/hw/mem/pc-dimm.c
> @@ -195,6 +195,33 @@ out:
>      return ret;
>  }
>  
> +static int pc_dimm_stat_mem_size(Object *obj, void *opaque)
> +{
> +    uint64_t *node_mem = opaque;
> +    int ret;
> +
> +    if (object_dynamic_cast(obj, TYPE_PC_DIMM)) {
> +        DeviceState *dev = DEVICE(obj);
> +        if (dev->realized && dev->hotplugged) {
Why cold-plugged memory is excluded?

> +            PCDIMMDevice *dimm = PC_DIMM(obj);
add line-break here

> +            int size = object_property_get_int(OBJECT(dimm), PC_DIMM_SIZE_PROP,
> +                                               NULL);
> +            if (size < 0) {
> +                return -1;
> +            }
It'd be better to check error returned by object_property_get_int() instead of
looking at size.

> +            node_mem[dimm->node] += size;
> +        }
> +    }
> +
> +    ret = object_child_foreach(obj, pc_dimm_stat_mem_size, opaque);
> +    return ret;
> +}
> +
> +void pc_dimm_stat_node_mem(uint64_t *node_mem)
> +{
> +    object_child_foreach(qdev_get_machine(), pc_dimm_stat_mem_size, node_mem);
> +}
> +
>  static Property pc_dimm_properties[] = {
>      DEFINE_PROP_UINT64(PC_DIMM_ADDR_PROP, PCDIMMDevice, addr, 0),
>      DEFINE_PROP_UINT32(PC_DIMM_NODE_PROP, PCDIMMDevice, node, 0),
> diff --git a/include/hw/mem/pc-dimm.h b/include/hw/mem/pc-dimm.h
> index 761eeef..0c9a8eb 100644
> --- a/include/hw/mem/pc-dimm.h
> +++ b/include/hw/mem/pc-dimm.h
> @@ -78,4 +78,6 @@ uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
>  int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp);
>  
>  int qmp_pc_dimm_device_list(Object *obj, void *opaque);
> +
> +void pc_dimm_stat_node_mem(uint64_t *node_mem);
>  #endif
> diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
> index d8539fd..cfc1592 100644
> --- a/include/sysemu/sysemu.h
> +++ b/include/sysemu/sysemu.h
> @@ -160,6 +160,7 @@ typedef struct node_info {
>  extern NodeInfo numa_info[MAX_NODES];
>  void set_numa_nodes(void);
>  void set_numa_modes(void);
> +int query_numa_node_mem(uint64_t *node_mem);
>  extern QemuOptsList qemu_numa_opts;
>  int numa_init_func(QemuOpts *opts, void *opaque);
>  
> diff --git a/monitor.c b/monitor.c
> index 7467521..c8c812f 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -1948,7 +1948,10 @@ static void do_info_numa(Monitor *mon, const QDict *qdict)
>  {
>      int i;
>      CPUState *cpu;
> +    uint64_t *node_mem;
>  
> +    node_mem = g_new0(uint64_t, nb_numa_nodes);
> +    query_numa_node_mem(node_mem);
>      monitor_printf(mon, "%d nodes\n", nb_numa_nodes);
>      for (i = 0; i < nb_numa_nodes; i++) {
>          monitor_printf(mon, "node %d cpus:", i);
> @@ -1959,8 +1962,9 @@ static void do_info_numa(Monitor *mon, const QDict *qdict)
>          }
>          monitor_printf(mon, "\n");
>          monitor_printf(mon, "node %d size: %" PRId64 " MB\n", i,
> -            numa_info[i].node_mem >> 20);
> +            node_mem[i] >> 20);
>      }
> +    g_free(node_mem);
>  }
>  
>  #ifdef CONFIG_PROFILER
> diff --git a/numa.c b/numa.c
> index 3b98135..4e27dd8 100644
> --- a/numa.c
> +++ b/numa.c
> @@ -35,6 +35,7 @@
>  #include "hw/boards.h"
>  #include "sysemu/hostmem.h"
>  #include "qmp-commands.h"
> +#include "hw/mem/pc-dimm.h"
>  
>  QemuOptsList qemu_numa_opts = {
>      .name = "numa",
> @@ -315,6 +316,20 @@ void memory_region_allocate_system_memory(MemoryRegion *mr, Object *owner,
>      }
>  }
>  
> +int query_numa_node_mem(uint64_t *node_mem)
> +{
> +    int i;
> +
> +    if (nb_numa_nodes <= 0) {
> +        return 0;
> +    }
> +    pc_dimm_stat_node_mem(node_mem);
> +    for (i = 0; i < nb_numa_nodes; i++) {
> +        node_mem[i] += numa_info[i].node_mem;
> +    }
> +    return 0;
> +}
> +
>  static int query_memdev(Object *obj, void *opaque)
>  {
>      MemdevList **list = opaque;
Zhanghailiang Sept. 20, 2014, 9:16 a.m. UTC | #4
On 2014/9/19 21:51, Igor Mammedov wrote:
> On Thu, 18 Sep 2014 20:07:08 +0800
> zhanghailiang <zhang.zhanghailiang@huawei.com> wrote:
>
>> When do memory hotplug, if there is numa node, we should add
>> the memory size to the corresponding node memory size.
>>
>> For now, it mainly affects the result of hmp command "info numa".
>>
>> Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
>> ---
>>   v2:
>> - Don't modify the numa_info.node_mem directly when treating hotplug memory,
>>    fix the "info numa" instead (suggested by Igor Mammedov)
>> ---
>>   hw/mem/pc-dimm.c         | 27 +++++++++++++++++++++++++++
>>   include/hw/mem/pc-dimm.h |  2 ++
>>   include/sysemu/sysemu.h  |  1 +
>>   monitor.c                |  6 +++++-
>>   numa.c                   | 15 +++++++++++++++
>>   5 files changed, 50 insertions(+), 1 deletion(-)
>>
>> diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
>> index 5bfc5b7..7b233a6 100644
>> --- a/hw/mem/pc-dimm.c
>> +++ b/hw/mem/pc-dimm.c
>> @@ -195,6 +195,33 @@ out:
>>       return ret;
>>   }
>>
>> +static int pc_dimm_stat_mem_size(Object *obj, void *opaque)
>> +{
>> +    uint64_t *node_mem = opaque;
>> +    int ret;
>> +
>> +    if (object_dynamic_cast(obj, TYPE_PC_DIMM)) {
>> +        DeviceState *dev = DEVICE(obj);
>> +        if (dev->realized && dev->hotplugged) {
> Why cold-plugged memory is excluded?
>

cold-plugged memory? Do you mean added at startup?
Er, in this case, it is wrong here,
i will remove the unnecessarily check of dev->hotplugged.;)

>> +            PCDIMMDevice *dimm = PC_DIMM(obj);
> add line-break here
>

OK!

>> +            int size = object_property_get_int(OBJECT(dimm), PC_DIMM_SIZE_PROP,
>> +                                               NULL);
>> +            if (size < 0) {
>> +                return -1;
>> +            }
> It'd be better to check error returned by object_property_get_int() instead of
> looking at size.
>

OK, will fix in V3. Thanks.

>> +            node_mem[dimm->node] += size;
>> +        }
>> +    }
>> +
>> +    ret = object_child_foreach(obj, pc_dimm_stat_mem_size, opaque);
>> +    return ret;
>> +}
>> +
>> +void pc_dimm_stat_node_mem(uint64_t *node_mem)
>> +{
>> +    object_child_foreach(qdev_get_machine(), pc_dimm_stat_mem_size, node_mem);
>> +}
>> +
>>   static Property pc_dimm_properties[] = {
>>       DEFINE_PROP_UINT64(PC_DIMM_ADDR_PROP, PCDIMMDevice, addr, 0),
>>       DEFINE_PROP_UINT32(PC_DIMM_NODE_PROP, PCDIMMDevice, node, 0),
>> diff --git a/include/hw/mem/pc-dimm.h b/include/hw/mem/pc-dimm.h
>> index 761eeef..0c9a8eb 100644
>> --- a/include/hw/mem/pc-dimm.h
>> +++ b/include/hw/mem/pc-dimm.h
>> @@ -78,4 +78,6 @@ uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
>>   int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp);
>>
>>   int qmp_pc_dimm_device_list(Object *obj, void *opaque);
>> +
>> +void pc_dimm_stat_node_mem(uint64_t *node_mem);
>>   #endif
>> diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
>> index d8539fd..cfc1592 100644
>> --- a/include/sysemu/sysemu.h
>> +++ b/include/sysemu/sysemu.h
>> @@ -160,6 +160,7 @@ typedef struct node_info {
>>   extern NodeInfo numa_info[MAX_NODES];
>>   void set_numa_nodes(void);
>>   void set_numa_modes(void);
>> +int query_numa_node_mem(uint64_t *node_mem);
>>   extern QemuOptsList qemu_numa_opts;
>>   int numa_init_func(QemuOpts *opts, void *opaque);
>>
>> diff --git a/monitor.c b/monitor.c
>> index 7467521..c8c812f 100644
>> --- a/monitor.c
>> +++ b/monitor.c
>> @@ -1948,7 +1948,10 @@ static void do_info_numa(Monitor *mon, const QDict *qdict)
>>   {
>>       int i;
>>       CPUState *cpu;
>> +    uint64_t *node_mem;
>>
>> +    node_mem = g_new0(uint64_t, nb_numa_nodes);
>> +    query_numa_node_mem(node_mem);
>>       monitor_printf(mon, "%d nodes\n", nb_numa_nodes);
>>       for (i = 0; i < nb_numa_nodes; i++) {
>>           monitor_printf(mon, "node %d cpus:", i);
>> @@ -1959,8 +1962,9 @@ static void do_info_numa(Monitor *mon, const QDict *qdict)
>>           }
>>           monitor_printf(mon, "\n");
>>           monitor_printf(mon, "node %d size: %" PRId64 " MB\n", i,
>> -            numa_info[i].node_mem >> 20);
>> +            node_mem[i] >> 20);
>>       }
>> +    g_free(node_mem);
>>   }
>>
>>   #ifdef CONFIG_PROFILER
>> diff --git a/numa.c b/numa.c
>> index 3b98135..4e27dd8 100644
>> --- a/numa.c
>> +++ b/numa.c
>> @@ -35,6 +35,7 @@
>>   #include "hw/boards.h"
>>   #include "sysemu/hostmem.h"
>>   #include "qmp-commands.h"
>> +#include "hw/mem/pc-dimm.h"
>>
>>   QemuOptsList qemu_numa_opts = {
>>       .name = "numa",
>> @@ -315,6 +316,20 @@ void memory_region_allocate_system_memory(MemoryRegion *mr, Object *owner,
>>       }
>>   }
>>
>> +int query_numa_node_mem(uint64_t *node_mem)
>> +{
>> +    int i;
>> +
>> +    if (nb_numa_nodes <= 0) {
>> +        return 0;
>> +    }
>> +    pc_dimm_stat_node_mem(node_mem);
>> +    for (i = 0; i < nb_numa_nodes; i++) {
>> +        node_mem[i] += numa_info[i].node_mem;
>> +    }
>> +    return 0;
>> +}
>> +
>>   static int query_memdev(Object *obj, void *opaque)
>>   {
>>       MemdevList **list = opaque;
>
>
> .
>
diff mbox

Patch

diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
index 5bfc5b7..7b233a6 100644
--- a/hw/mem/pc-dimm.c
+++ b/hw/mem/pc-dimm.c
@@ -195,6 +195,33 @@  out:
     return ret;
 }
 
+static int pc_dimm_stat_mem_size(Object *obj, void *opaque)
+{
+    uint64_t *node_mem = opaque;
+    int ret;
+
+    if (object_dynamic_cast(obj, TYPE_PC_DIMM)) {
+        DeviceState *dev = DEVICE(obj);
+        if (dev->realized && dev->hotplugged) {
+            PCDIMMDevice *dimm = PC_DIMM(obj);
+            int size = object_property_get_int(OBJECT(dimm), PC_DIMM_SIZE_PROP,
+                                               NULL);
+            if (size < 0) {
+                return -1;
+            }
+            node_mem[dimm->node] += size;
+        }
+    }
+
+    ret = object_child_foreach(obj, pc_dimm_stat_mem_size, opaque);
+    return ret;
+}
+
+void pc_dimm_stat_node_mem(uint64_t *node_mem)
+{
+    object_child_foreach(qdev_get_machine(), pc_dimm_stat_mem_size, node_mem);
+}
+
 static Property pc_dimm_properties[] = {
     DEFINE_PROP_UINT64(PC_DIMM_ADDR_PROP, PCDIMMDevice, addr, 0),
     DEFINE_PROP_UINT32(PC_DIMM_NODE_PROP, PCDIMMDevice, node, 0),
diff --git a/include/hw/mem/pc-dimm.h b/include/hw/mem/pc-dimm.h
index 761eeef..0c9a8eb 100644
--- a/include/hw/mem/pc-dimm.h
+++ b/include/hw/mem/pc-dimm.h
@@ -78,4 +78,6 @@  uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
 int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp);
 
 int qmp_pc_dimm_device_list(Object *obj, void *opaque);
+
+void pc_dimm_stat_node_mem(uint64_t *node_mem);
 #endif
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index d8539fd..cfc1592 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -160,6 +160,7 @@  typedef struct node_info {
 extern NodeInfo numa_info[MAX_NODES];
 void set_numa_nodes(void);
 void set_numa_modes(void);
+int query_numa_node_mem(uint64_t *node_mem);
 extern QemuOptsList qemu_numa_opts;
 int numa_init_func(QemuOpts *opts, void *opaque);
 
diff --git a/monitor.c b/monitor.c
index 7467521..c8c812f 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1948,7 +1948,10 @@  static void do_info_numa(Monitor *mon, const QDict *qdict)
 {
     int i;
     CPUState *cpu;
+    uint64_t *node_mem;
 
+    node_mem = g_new0(uint64_t, nb_numa_nodes);
+    query_numa_node_mem(node_mem);
     monitor_printf(mon, "%d nodes\n", nb_numa_nodes);
     for (i = 0; i < nb_numa_nodes; i++) {
         monitor_printf(mon, "node %d cpus:", i);
@@ -1959,8 +1962,9 @@  static void do_info_numa(Monitor *mon, const QDict *qdict)
         }
         monitor_printf(mon, "\n");
         monitor_printf(mon, "node %d size: %" PRId64 " MB\n", i,
-            numa_info[i].node_mem >> 20);
+            node_mem[i] >> 20);
     }
+    g_free(node_mem);
 }
 
 #ifdef CONFIG_PROFILER
diff --git a/numa.c b/numa.c
index 3b98135..4e27dd8 100644
--- a/numa.c
+++ b/numa.c
@@ -35,6 +35,7 @@ 
 #include "hw/boards.h"
 #include "sysemu/hostmem.h"
 #include "qmp-commands.h"
+#include "hw/mem/pc-dimm.h"
 
 QemuOptsList qemu_numa_opts = {
     .name = "numa",
@@ -315,6 +316,20 @@  void memory_region_allocate_system_memory(MemoryRegion *mr, Object *owner,
     }
 }
 
+int query_numa_node_mem(uint64_t *node_mem)
+{
+    int i;
+
+    if (nb_numa_nodes <= 0) {
+        return 0;
+    }
+    pc_dimm_stat_node_mem(node_mem);
+    for (i = 0; i < nb_numa_nodes; i++) {
+        node_mem[i] += numa_info[i].node_mem;
+    }
+    return 0;
+}
+
 static int query_memdev(Object *obj, void *opaque)
 {
     MemdevList **list = opaque;