QEMU源码全解析2 —— QEMU参数解析(2)

接前一篇文章: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,存储了所有的可用选项,代码如下:

扫描二维码关注公众号,回复: 15602912 查看本文章
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参数解析的更多细节,且看下回分解。

猜你喜欢

转载自blog.csdn.net/phmatthaus/article/details/131521941