Advertisement
otubo

dimmpop

Jul 22nd, 2015
307
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 9.36 KB | None | 0 0
  1. commit c547e9863a482729d7bf5ccccf2a53dedfed140b
  2. Author: Eduardo Otubo <eduardo.otubo@profitbricks.com>
  3. Date:   Mon Jun 15 10:10:06 2015 +0200
  4.  
  5.     dimmpop: implementation of dimmpop
  6.    
  7.     Implement -dimmpop option to populate dimms at bootup
  8.      syntax: -dimmpop pfx=poolid,slots=n,size=XGB
  9.    
  10.     This will populate n dimms with ids poolid0, ..., poolidn-1, each one of
  11.     size XGB
  12.    
  13.     Signed-off-by: Anshul Makkar <anshul.makkar@profitbricks.com>
  14.     Signed-off-by: Eduardo Otubo <eduardo.otubo@profitbricks.com>
  15.  
  16. diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
  17. index 39f0c97..55343b0 100644
  18. --- a/hw/mem/pc-dimm.c
  19. +++ b/hw/mem/pc-dimm.c
  20. @@ -370,4 +370,53 @@ static void pc_dimm_register_types(void)
  21.      type_register_static(&pc_dimm_info);
  22.  }
  23.  
  24. +/* desc: activate newly added dimm devices through dimmpop
  25. + * id: id of the dimm device like pool0, pool1
  26. + * size: size of the newly added dimm device.
  27. + * return : success or failure.
  28. + */
  29. +int pc_dimm_activate(const char *id, uint64_t size)
  30. +{
  31. +    char dimmid[32];
  32. +    int ret = 0;
  33. +    Error *local_err = NULL;
  34. +    QmpInputVisitor *qiv;
  35. +
  36. +    strcpy(dimmid, id);
  37. +    strncat(dimmid, "-memdev", 7);
  38. +
  39. +    QDict *sizeqdict;
  40. +    sizeqdict = qdict_new();
  41. +    QInt *sizeobj = qint_from_int(size);
  42. +    qdict_put(sizeqdict, "size", sizeobj);
  43. +
  44. +    qiv = qmp_input_visitor_new(QOBJECT(sizeobj));
  45. +    object_add("memory-backend-ram", dimmid, sizeqdict, qmp_input_get_visitor(qiv), &local_err);
  46. +    qmp_input_visitor_cleanup(qiv);
  47. +    if (local_err) {
  48. +        qerror_report_err(local_err);
  49. +        error_free(local_err);
  50. +        fprintf(stderr, "Object memdev creation failure \n");
  51. +        ret = -EINVAL;
  52. +    }
  53. +
  54. +    QemuOpts *dimmopts = qemu_opts_create(qemu_find_opts("device"), id, 0, &error_abort);
  55. +    qemu_opt_set(dimmopts, "driver", TYPE_PC_DIMM, &error_abort);
  56. +    qemu_opt_set(dimmopts, "memdev", dimmid, &error_abort);
  57. +
  58. +    /* no need for device addition. It is automatically taken care of when qemu calls device
  59. +     * init functions. Only thing is that we need to define device properties correctly
  60. +     */
  61. +#if 0
  62. +    char num[16];
  63. +    DeviceState *dev;
  64. +    dev = qdev_device_add(dimmopts);
  65. +    if (!dev)
  66. +    {
  67. +        fprintf(stderr, "Failed to add the dimm device \"%s\" \n", id);
  68. +    }
  69. +#endif
  70. +    return ret;
  71. +}
  72. +
  73.  type_init(pc_dimm_register_types)
  74. diff --git a/include/hw/mem/pc-dimm.h b/include/hw/mem/pc-dimm.h
  75. index f7b80b4..981477d 100644
  76. --- a/include/hw/mem/pc-dimm.h
  77. +++ b/include/hw/mem/pc-dimm.h
  78. @@ -19,6 +19,11 @@
  79.  #include "exec/memory.h"
  80.  #include "sysemu/hostmem.h"
  81.  #include "hw/qdev.h"
  82. +#include "qapi/qmp/qint.h"
  83. +#include "qapi/qmp-input-visitor.h"
  84. +#include "qmp-commands.h"
  85. +#include "qapi/qmp/qobject.h"
  86. +#include "monitor/qdev.h"
  87.  
  88.  #define DEFAULT_PC_DIMMSIZE (1024*1024*1024)
  89.  
  90. @@ -76,6 +81,7 @@ uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
  91.                                 Error **errp);
  92.  
  93.  int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp);
  94. +int pc_dimm_activate(const char *id, uint64_t size);
  95.  
  96.  int qmp_pc_dimm_device_list(Object *obj, void *opaque);
  97.  uint64_t pc_existing_dimms_capacity(Error **errp);
  98. diff --git a/qemu-options.hx b/qemu-options.hx
  99. index 319d971..8a23ff5 100644
  100. --- a/qemu-options.hx
  101. +++ b/qemu-options.hx
  102. @@ -3462,6 +3462,22 @@ Dump json-encoded vmstate information for current machine type to file
  103.  in @var{file}
  104.  ETEXI
  105.  
  106. +DEF("dimmpop", HAS_ARG, QEMU_OPTION_dimmpop,
  107. +   "-dimmpop [pfx=pool][,slots=n][,size=size]\n"
  108. +   "               configure dimms at system startup\n"
  109. +   "               pool: logical parition for dimm device\n"
  110. +   "               slots: number of dimm devices\n"
  111. +   "               size: size of each dimm (default: none\n",
  112. +   QEMU_ARCH_ALL)
  113. +STEXI
  114. +@item -dimmpop [size=]@var{megs}
  115. +@findex -m
  116. +Set virtual RAM size to @var{megs} megabytes. Default is 128 MiB.  Optionally,
  117. +a suffix of ``M'' or ``G'' can be used to signify a value in megabytes or
  118. +gigabytes respectively. Optional pair @var{slots}, @var{maxmem} could be used
  119. +to set amount of hotluggable memory slots and possible maximum amount of memory.
  120. +ETEXI
  121. +
  122.  HXCOMM This is the last statement. Insert new options before this line!
  123.  STEXI
  124.  @end table
  125. diff --git a/util/qemu-config.c b/util/qemu-config.c
  126. index 2d32ce7..9536915 100644
  127. --- a/util/qemu-config.c
  128. +++ b/util/qemu-config.c
  129. @@ -8,7 +8,7 @@
  130.  #include "qmp-commands.h"
  131.  #include "hw/i386/pc.h"
  132.  
  133. -static QemuOptsList *vm_config_groups[32];
  134. +static QemuOptsList *vm_config_groups[64];
  135.  static QemuOptsList *drive_config_groups[4];
  136.  
  137.  static QemuOptsList *find_list(QemuOptsList **lists, const char *group,
  138. diff --git a/vl.c b/vl.c
  139. index 74c2681..2168d95 100644
  140. --- a/vl.c
  141. +++ b/vl.c
  142. @@ -27,6 +27,7 @@
  143.  #include <time.h>
  144.  #include <errno.h>
  145.  #include <sys/time.h>
  146. +#include "hw/mem/pc-dimm.h"
  147.  
  148.  #include "config-host.h"
  149.  
  150. @@ -124,7 +125,6 @@ int main(int argc, char **argv)
  151.  
  152.  #define MAX_VIRTIO_CONSOLES 1
  153.  #define MAX_SCLP_CONSOLES 1
  154. -
  155.  static const char *data_dir[16];
  156.  static int data_dir_idx;
  157.  const char *bios_name = NULL;
  158. @@ -490,6 +490,29 @@ static QemuOptsList qemu_semihosting_config_opts = {
  159.      },
  160.  };
  161.  
  162. +/* Dimmpop option: Used to populate VM with dimms of specific size at startup */
  163. +static QemuOptsList qemu_dimmpop_opts = {
  164. +    .name = "dimmpop",
  165. +    .head = QTAILQ_HEAD_INITIALIZER(qemu_dimmpop_opts.head),
  166. +    .desc = {
  167. +        {
  168. +            .name = "pfx",
  169. +            .type = QEMU_OPT_STRING,
  170. +            .help = "pool prefix for this dimm device",
  171. +        }, {
  172. +            .name = "slots",
  173. +            .type = QEMU_OPT_SIZE,
  174. +            .help = "number of dimm devices to populate",
  175. +
  176. +        }, {
  177. +            .name = "size",
  178. +            .type = QEMU_OPT_SIZE,
  179. +            .help = "size of each dimm device to populate",
  180. +        },
  181. +   { /* end of the list */ }
  182. +    },
  183. +};
  184. +
  185.  /**
  186.   * Get machine options
  187.   *
  188. @@ -788,6 +811,62 @@ static void configure_rtc_date_offset(const char *startdate, int legacy)
  189.      }
  190.  }
  191.  
  192. +/* desc: populate dimms at the startup using dimmpop
  193. + * param: command line options.
  194. + * return: null
  195. + */
  196. +static void configure_dimmpop(QemuOpts *opts)
  197. +{
  198. +    const char *value, *pfx, *id;
  199. +    int num, dimm;
  200. +    uint64_t size;
  201. +    const char *mem_str;
  202. +    char buf[32];
  203. +    ram_addr_t ram_size = 1024;
  204. +
  205. +    id = qemu_opts_id(opts);
  206. +    value = qemu_opt_get(opts, "pfx");
  207. +    if (!value)
  208. +    {
  209. +        fprintf(stderr, "qemu: invalid prefix for dimm pool '%s'\n", id);
  210. +        exit(1);
  211. +    }
  212. +
  213. +    pfx = value;
  214. +    value = qemu_opt_get(opts, "slots");
  215. +    if (!value) {
  216. +        fprintf(stderr, "qemu: slots not defined for dimm pool '%s'\n", pfx);
  217. +        exit(1);
  218. +    }
  219. +    else num = atoi(value);
  220. +
  221. +    mem_str = qemu_opt_get(opts, "size");
  222. +    if (!mem_str)
  223. +    {
  224. +        fprintf(stderr, "qemu: size not defined for the dimm pool.\n");
  225. +        exit(1);
  226. +    }
  227. +    size = qemu_opt_get_size(opts, "size", ram_size);
  228. +
  229. +    /* Fix up legacy suffix-less format */
  230. +    if (g_ascii_isdigit(mem_str[strlen(mem_str) - 1]))
  231. +    {
  232. +        uint64_t overflow_check = size;
  233. +        size <<= 20;
  234. +        if ((size >> 20) != overflow_check)
  235. +        {
  236. +            error_report("too large 'size' option value");
  237. +            exit(EXIT_FAILURE);
  238. +        }
  239. +    }
  240. +    for (dimm = 0; dimm < num; dimm++)
  241. +    {
  242. +        sprintf(buf, "%s%d", pfx, dimm);
  243. +        if (pc_dimm_activate(buf, size))
  244. +            fprintf(stderr, "qemu: dimm %s not defined for dimm pool '%s'\n", buf, pfx);
  245. +    }
  246. +}
  247. +
  248.  static void configure_rtc(QemuOpts *opts)
  249.  {
  250.      const char *value;
  251. @@ -2767,6 +2846,7 @@ int main(int argc, char **argv, char **envp)
  252.      uint64_t ram_slots = 0;
  253.      FILE *vmstate_dump_file = NULL;
  254.      Error *main_loop_err = NULL;
  255. +    QemuOpts *dimmpop_opts = NULL;
  256.  
  257.      qemu_init_cpu_loop();
  258.      qemu_mutex_lock_iothread();
  259. @@ -2806,6 +2886,7 @@ int main(int argc, char **argv, char **envp)
  260.      qemu_add_opts(&qemu_numa_opts);
  261.      qemu_add_opts(&qemu_icount_opts);
  262.      qemu_add_opts(&qemu_semihosting_config_opts);
  263. +    qemu_add_opts(&qemu_dimmpop_opts);
  264.  
  265.      runstate_init();
  266.  
  267. @@ -3753,6 +3834,14 @@ int main(int argc, char **argv, char **envp)
  268.                      exit(1);
  269.                  }
  270.                  break;
  271. +            case QEMU_OPTION_dimmpop:
  272. +                dimmpop_opts = qemu_opts_parse(qemu_find_opts("dimmpop"), optarg, 0);
  273. +                if (!dimmpop_opts)
  274. +                {
  275. +                    fprintf(stderr, "Failed to get dimmpop options \n");
  276. +                    exit(1);
  277. +                }
  278. +                break;
  279.              default:
  280.                  os_parse_cmd_args(popt->index, optarg);
  281.              }
  282. @@ -4239,6 +4328,14 @@ int main(int argc, char **argv, char **envp)
  283.              exit(1);
  284.      }
  285.  
  286. +    /* The location of configure_dimmpop is important. We need to make sure the it is called
  287. +     * before the device_init_func is called for each device as in configure_dimmpop we are
  288. +     * calling dimm_activate that creates the object (object_add). This is important before
  289. +     * device initialization.
  290. +     */
  291. +    if(dimmpop_opts)
  292. +        configure_dimmpop(dimmpop_opts);
  293. +
  294.      /* init generic devices */
  295.      if (qemu_opts_foreach(qemu_find_opts("device"), device_init_func, NULL, 1) != 0)
  296.          exit(1);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement