Full analysis of QEMU source code 2 - QEMU parameter analysis (2)

Continued from the previous article: QEMU source code full analysis 1 - QEMU parameter analysis (1)

References for the content of this article:

"Interesting Talk about Linux Operating System" —— Liu Chao, Geek Time

"QEMU/KVM" source code analysis and application - Li Qiang, Machinery Industry Press

Thank you very much!

Last time, we talked about how so many parameters are parsed by QEMU. In this section, we will look at the specific parsing process.

QEMU uses QEMUOption to represent the parameter options of the QEMU program. The definition of QEMUOption is also in softmmu/vl.c. The code is as follows:

typedef struct QEMUOption {
    const char *name;
    int flags;
    int index;
    uint32_t arch_mask;
} QEMUOption;

in:

  • name: Indicates the name of the parameter option.
  • flags: Indicates the attributes of some parameter options in the option, such as whether there are sub-parameters.
  • arch_mask indicates the architecture supported by the parameter.

softmmu/vl.c defines a variable qemu_options of QEMUOption structure in the global scope, which stores all available options. The code is as follows:

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 */ }
};

The main function will call lookup_opt to parse the QEMU command line parameters. The parameters not in qemu_options are illegal. code show as below:

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;
}

Some readers may have doubts. There are not many items in the static const QEMUOption qemu_options[] structure array. How do you parse so many parameters? You have to look carefully, there is such a line of code in the structure:

#include "qemu-options.def"

Let's take a look at the contents of the qemu-options.def file. The result of searching this file is not found. This file will be generated after compiling the QEMU source code (in fact, it is generated according to the qemu-options.hx file using the scripts/hxtool script in the Makefile). According to QEMU zero knowledge learning 3 - QEMU configuration_qemu configuration file_Blue Sky Lay's Blog-CSDN Blog

In the method, run ./configure in the root directory of the QEMU source code to configure. Light configuration is not enough, you have to follow QEMU zero-knowledge learning 4 - QEMU compilation - Programmer Sought

The method in the QEMU source code can only be compiled and built by running make in the root directory of the QEMU source code. Finally, the qemu-options.def file will be generated in the build directory. The content of the file is as follows (a total of more than 1000 lines, only part of the content is intercepted):

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

Here you only need to understand that qemu_options includes all possible parameter options, such as "-enable-kvm", "-smp", "-realtime", "-device" and so on above.

For more details on QEMUOption and QEMU parameter parsing, see the next chapter.

Guess you like

Origin blog.csdn.net/phmatthaus/article/details/131521941