接前一篇文章: QEMU源码全解析1 —— QEMU参数解析(1)
本文内容参考:
《趣谈 Linux 操作系统》 —— 刘超, 极客时间
《 QEMU /KVM》源码解析与应用 —— 李强,机械工业出版社
特此致谢!
上回说到如此多的参数是如何被QEMU解析的,本节就来看一下具体的解析过程。
QEMU使用QEMUOption来表示QEMU程序的参数选项,QEMUOption的定义也是在softmmu/vl.c中,代码如下:
- typedef struct QEMUOption {
- const char *name;
- int flags;
- int index;
- uint32_t arch_mask;
- } QEMUOption;
其中:
- name:表示参数选项的名称。
- flags:表示选项中一些参数选项的属性,比如是否有子参数。
- arch_mask表示参数支持的体系结构。
softmmu/vl.c在全局范围内定义了一个QEMUOption结构的变量qemu_options,存储了所有的可用选项,代码如下:
- static const QEMUOption qemu_options[] = {
- { "h", 0, QEMU_OPTION_h, QEMU_ARCH_ALL },
-
- #define DEF(option, opt_arg, opt_enum, opt_help, arch_mask) \
- { option, opt_arg, opt_enum, arch_mask },
- #define DEFHEADING(text)
- #define ARCHHEADING(text, arch_mask)
-
- #include "qemu-options.def"
- { /* end of list */ }
- };
main函数中会调用lookup_opt来解析QEMU命令行参数,不在qemu_options中的参数是不合法的。代码如下:
- static const QEMUOption *lookup_opt(int argc, char **argv,
- const char **poptarg, int *poptind)
- {
- const QEMUOption *popt;
- int optind = *poptind;
- char *r = argv[optind];
- const char *optarg;
-
- loc_set_cmdline(argv, optind, 1);
- optind++;
- /* Treat --foo the same as -foo. */
- if (r[1] == '-')
- r++;
- popt = qemu_options;
- for(;;) {
- if (!popt->name) {
- error_report("invalid option");
- exit(1);
- }
- if (!strcmp(popt->name, r + 1))
- break;
- popt++;
- }
- if (popt->flags & HAS_ARG) {
- if (optind >= argc) {
- error_report("requires an argument");
- exit(1);
- }
- optarg = argv[optind++];
- loc_set_cmdline(argv, optind - 2, 2);
- } else {
- optarg = NULL;
- }
-
- *poptarg = optarg;
- *poptind = optind;
-
- return popt;
- }
有的读者可能会有疑问,static const QEMUOption qemu_options[]结构体数组中也没有几项啊,是如何做到解析那么多参数的?你得仔细看,结构体中有这样一行代码:
#include "qemu-options.def"
再来看看qemu-options.def文件的内容。搜索这个文件结果没有搜索到,要在编译QEMU源码后,这个文件才会生成(实际上是在Makefile中利用scripts/hxtool脚本根据qemu-options.hx文件生成的)。按照 QEMU零知识学习3 —— QEMU配置_qemu 配置文件_蓝天居士的博客-CSDN博客
中的方法,在QEMU源码根目录下运行./configure进行配置。光配置还不够,还得按照 QEMU零知识学习4 —— QEMU编译_蓝天居士的博客-CSDN博客
中的方法,在QEMU源码根目录下运行make进行编译构建才可以。最终在build目录下会生成qemu-options.def文件,文件内容如下(一共1000多行,仅截取部分内容):
- DEFHEADING(Standard options:)
-
- DEF("help", 0, QEMU_OPTION_h,
- "-h or -help display this help and exit\n", QEMU_ARCH_ALL)
-
- DEF("version", 0, QEMU_OPTION_version,
- "-version display version information and exit\n", QEMU_ARCH_ALL)
-
- DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
- "-machine [type=]name[,prop[=value][,...]]\n"
- " selects emulated machine ('-machine help' for list)\n"
- " property accel=accel1[:accel2[:...]] selects accelerator\n"
- " supported accelerators are kvm, xen, hax, hvf, nvmm, whpx or tcg (default: tcg)\n"
- " vmport=on|off|auto controls emulation of vmport (default: auto)\n"
- " dump-guest-core=on|off include guest memory in a core dump (default=on)\n"
- " mem-merge=on|off controls memory merge support (default: on)\n"
- " aes-key-wrap=on|off controls support for AES key wrapping (default=on)\n"
- " dea-key-wrap=on|off controls support for DEA key wrapping (default=on)\n"
- " suppress-vmdesc=on|off disables self-describing migration (default=off)\n"
- " nvdimm=on|off controls NVDIMM support (default=off)\n"
- " memory-encryption=@var{} memory encryption object to use (default=none)\n"
- " hmat=on|off controls ACPI HMAT support (default=off)\n"
- " memory-backend='backend-id' specifies explicitly provided backend for main RAM (default=none)\n"
- " cxl-fmw.0.targets.0=firsttarget,cxl-fmw.0.targets.1=secondtarget,cxl-fmw.0.size=size[,cxl-fmw.0.interleave-granularity=granularity]\n",
- QEMU_ARCH_ALL)
-
- DEF("M", HAS_ARG, QEMU_OPTION_M,
- " sgx-epc.0.memdev=memid,sgx-epc.0.node=numaid\n",
- QEMU_ARCH_ALL)
-
-
- DEF("cpu", HAS_ARG, QEMU_OPTION_cpu,
- "-cpu cpu select CPU ('-cpu help' for list)\n", QEMU_ARCH_ALL)
-
- DEF("accel", HAS_ARG, QEMU_OPTION_accel,
- "-accel [accel=]accelerator[,prop[=value][,...]]\n"
- " select accelerator (kvm, xen, hax, hvf, nvmm, whpx or tcg; use 'help' for a list)\n"
- " igd-passthru=on|off (enable Xen integrated Intel graphics passthrough, default=off)\n"
- " kernel-irqchip=on|off|split controls accelerated irqchip support (default=on)\n"
- " kvm-shadow-mem=size of KVM shadow MMU in bytes\n"
- " split-wx=on|off (enable TCG split w^x mapping)\n"
- " tb-size=n (TCG translation block cache size)\n"
- " dirty-ring-size=n (KVM dirty ring GFN count, default 0)\n"
- " thread=single|multi (enable multi-threaded TCG)\n", QEMU_ARCH_ALL)
-
- DEF("smp", HAS_ARG, QEMU_OPTION_smp,
- "-smp [[cpus=]n][,maxcpus=maxcpus][,sockets=sockets][,dies=dies][,clusters=clusters][,cores=cores][,threads=threads]\n"
- " set the number of initial CPUs to 'n' [default=1]\n"
- " maxcpus= maximum number of total CPUs, including\n"
- " offline CPUs for hotplug, etc\n"
- " sockets= number of sockets on the machine board\n"
- " dies= number of dies in one socket\n"
- " clusters= number of clusters in one die\n"
- " cores= number of cores in one cluster\n"
- " threads= number of threads in one core\n"
- "Note: Different machines may have different subsets of the CPU topology\n"
- " parameters supported, so the actual meaning of the supported parameters\n"
- " will vary accordingly. For example, for a machine type that supports a\n"
- " three-level CPU hierarchy of sockets/cores/threads, the parameters will\n"
- " sequentially mean as below:\n"
- " sockets means the number of sockets on the machine board\n"
- " cores means the number of cores in one socket\n"
- " threads means the number of threads in one core\n"
- " For a particular machine type board, an expected CPU topology hierarchy\n"
- " can be defined through the supported sub-option. Unsupported parameters\n"
- " can also be provided in addition to the sub-option, but their values\n"
- " must be set as 1 in the purpose of correct parsing.\n",
- QEMU_ARCH_ALL)
-
- DEF("numa", HAS_ARG, QEMU_OPTION_numa,
- "-numa node[,mem=size][,cpus=firstcpu[-lastcpu]][,nodeid=node][,initiator=node]\n"
- "-numa node[,memdev=id][,cpus=firstcpu[-lastcpu]][,nodeid=node][,initiator=node]\n"
- "-numa dist,src=source,dst=destination,val=distance\n"
- "-numa cpu,node-id=node[,socket-id=x][,core-id=y][,thread-id=z]\n"
- "-numa hmat-lb,initiator=node,target=node,hierarchy=memory|first-level|second-level|third-level,data-type=access-latency|read-latency|write-latency[,latency=lat][,bandwidth=bw]\n"
- "-numa hmat-cache,node-id=node,size=size,level=level[,associativity=none|direct|complex][,policy=none|write-back|write-through][,line=size]\n",
- QEMU_ARCH_ALL)
-
- ……
-
- #ifndef _WIN32
- DEF("chroot", HAS_ARG, QEMU_OPTION_chroot, \
- "-chroot dir chroot to dir just before starting the VM\n",
- QEMU_ARCH_ALL)
- #endif
-
- #ifndef _WIN32
- DEF("runas", HAS_ARG, QEMU_OPTION_runas, \
- "-runas user change to user id user just before starting the VM\n" \
- " user can be numeric uid:gid instead\n",
- QEMU_ARCH_ALL)
- #endif
-
- DEF("prom-env", HAS_ARG, QEMU_OPTION_prom_env,
- "-prom-env variable=value\n"
- " set OpenBIOS nvram variables\n",
- QEMU_ARCH_PPC | QEMU_ARCH_SPARC)
- DEF("semihosting", 0, QEMU_OPTION_semihosting,
- "-semihosting semihosting mode\n",
- QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA |
- QEMU_ARCH_MIPS | QEMU_ARCH_NIOS2 | QEMU_ARCH_RISCV)
- DEF("semihosting-config", HAS_ARG, QEMU_OPTION_semihosting_config,
- "-semihosting-config [enable=on|off][,target=native|gdb|auto][,chardev=id][,arg=str[,...]]\n" \
- " semihosting configuration\n",
- QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA |
- QEMU_ARCH_MIPS | QEMU_ARCH_NIOS2 | QEMU_ARCH_RISCV)
- DEF("old-param", 0, QEMU_OPTION_old_param,
- "-old-param old param mode\n", QEMU_ARCH_ARM)
-
- DEF("sandbox", HAS_ARG, QEMU_OPTION_sandbox, \
- "-sandbox on[,obsolete=allow|deny][,elevateprivileges=allow|deny|children]\n" \
- " [,spawn=allow|deny][,resourcecontrol=allow|deny]\n" \
- " Enable seccomp mode 2 system call filter (default 'off').\n" \
- " use 'obsolete' to allow obsolete system calls that are provided\n" \
- " by the kernel, but typically no longer used by modern\n" \
- " C library implementations.\n" \
- " use 'elevateprivileges' to allow or deny the QEMU process ability\n" \
- " to elevate privileges using set*uid|gid system calls.\n" \
- " The value 'children' will deny set*uid|gid system calls for\n" \
- " main QEMU process but will allow forks and execves to run unprivileged\n" \
- " use 'spawn' to avoid QEMU to spawn new threads or processes by\n" \
- " blocking *fork and execve\n" \
- " use 'resourcecontrol' to disable process affinity and schedular priority\n",
- QEMU_ARCH_ALL)
-
- DEF("readconfig", HAS_ARG, QEMU_OPTION_readconfig,
- "-readconfig <file>\n"
- " read config file\n", QEMU_ARCH_ALL)
-
- DEF("no-user-config", 0, QEMU_OPTION_nouserconfig,
- "-no-user-config\n"
- " do not load default user-provided config files at startup\n",
- QEMU_ARCH_ALL)
-
- DEF("trace", HAS_ARG, QEMU_OPTION_trace,
- "-trace [[enable=]<pattern>][,events=<file>][,file=<file>]\n"
- " specify tracing options\n",
- QEMU_ARCH_ALL)
- DEF("plugin", HAS_ARG, QEMU_OPTION_plugin,
- "-plugin [file=]<file>[,<argname>=<argvalue>]\n"
- " load a plugin\n",
- QEMU_ARCH_ALL)
-
- DEF("qtest", HAS_ARG, QEMU_OPTION_qtest, "", QEMU_ARCH_ALL)
- DEF("qtest-log", HAS_ARG, QEMU_OPTION_qtest_log, "", QEMU_ARCH_ALL)
-
- DEF("msg", HAS_ARG, QEMU_OPTION_msg,
- "-msg [timestamp[=on|off]][,guest-name=[on|off]]\n"
- " control error message format\n"
- " timestamp=on enables timestamps (default: off)\n"
- " guest-name=on enables guest name prefix but only if\n"
- " -name guest option is set (default: off)\n",
- QEMU_ARCH_ALL)
-
- DEF("dump-vmstate", HAS_ARG, QEMU_OPTION_dump_vmstate,
- "-dump-vmstate <file>\n"
- " Output vmstate information in JSON format to file.\n"
- " Use the scripts/vmstate-static-checker.py file to\n"
- " check for possible regressions in migration code\n"
- " by comparing two such vmstate dumps.\n",
- QEMU_ARCH_ALL)
-
- DEF("enable-sync-profile", 0, QEMU_OPTION_enable_sync_profile,
- "-enable-sync-profile\n"
- " enable synchronization profiling\n",
- QEMU_ARCH_ALL)
-
- DEFHEADING()
-
- DEFHEADING(Generic object creation:)
-
- DEF("object", HAS_ARG, QEMU_OPTION_object,
- "-object TYPENAME[,PROP1=VALUE1,...]\n"
- " create a new object of type TYPENAME setting properties\n"
- " in the order they are specified. Note that the 'id'\n"
- " property must be set. These objects are placed in the\n"
- " '/objects' path.\n",
- QEMU_ARCH_ALL)
-
-
-
- #undef DEF
- #undef DEFHEADING
- #undef ARCHHEADING
这里只需要理解qemu_options中包括了所有可能的参数选项,如上边的“-enable- kvm ”、“-smp”、“-realtime”、“-device”等即可。
欲知QEMUOption以及QEMU参数解析的更多细节,且看下回分解。