cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

config.c (5252B)


      1/*
      2 * Semihosting configuration
      3 *
      4 * Copyright (c) 2015 Imagination Technologies
      5 * Copyright (c) 2019 Linaro Ltd
      6 *
      7 * This controls the configuration of semihosting for all guest
      8 * targets that support it. Architecture specific handling is handled
      9 * in target/HW/HW-semi.c
     10 *
     11 * Semihosting is sightly strange in that it is also supported by some
     12 * linux-user targets. However in that use case no configuration of
     13 * the outputs and command lines is supported.
     14 *
     15 * The config module is common to all softmmu targets however as vl.c
     16 * needs to link against the helpers.
     17 *
     18 * SPDX-License-Identifier: GPL-2.0-or-later
     19 */
     20
     21#include "qemu/osdep.h"
     22#include "qemu/option.h"
     23#include "qemu/config-file.h"
     24#include "qemu/error-report.h"
     25#include "semihosting/semihost.h"
     26#include "chardev/char.h"
     27
     28QemuOptsList qemu_semihosting_config_opts = {
     29    .name = "semihosting-config",
     30    .implied_opt_name = "enable",
     31    .head = QTAILQ_HEAD_INITIALIZER(qemu_semihosting_config_opts.head),
     32    .desc = {
     33        {
     34            .name = "enable",
     35            .type = QEMU_OPT_BOOL,
     36        }, {
     37            .name = "target",
     38            .type = QEMU_OPT_STRING,
     39        }, {
     40            .name = "chardev",
     41            .type = QEMU_OPT_STRING,
     42        }, {
     43            .name = "arg",
     44            .type = QEMU_OPT_STRING,
     45        },
     46        { /* end of list */ }
     47    },
     48};
     49
     50typedef struct SemihostingConfig {
     51    bool enabled;
     52    SemihostingTarget target;
     53    Chardev *chardev;
     54    const char **argv;
     55    int argc;
     56    const char *cmdline; /* concatenated argv */
     57} SemihostingConfig;
     58
     59static SemihostingConfig semihosting;
     60static const char *semihost_chardev;
     61
     62bool semihosting_enabled(void)
     63{
     64    return semihosting.enabled;
     65}
     66
     67SemihostingTarget semihosting_get_target(void)
     68{
     69    return semihosting.target;
     70}
     71
     72const char *semihosting_get_arg(int i)
     73{
     74    if (i >= semihosting.argc) {
     75        return NULL;
     76    }
     77    return semihosting.argv[i];
     78}
     79
     80int semihosting_get_argc(void)
     81{
     82    return semihosting.argc;
     83}
     84
     85const char *semihosting_get_cmdline(void)
     86{
     87    if (semihosting.cmdline == NULL && semihosting.argc > 0) {
     88        semihosting.cmdline = g_strjoinv(" ", (gchar **)semihosting.argv);
     89    }
     90    return semihosting.cmdline;
     91}
     92
     93static int add_semihosting_arg(void *opaque,
     94                               const char *name, const char *val,
     95                               Error **errp)
     96{
     97    SemihostingConfig *s = opaque;
     98    if (strcmp(name, "arg") == 0) {
     99        s->argc++;
    100        /* one extra element as g_strjoinv() expects NULL-terminated array */
    101        s->argv = g_realloc(s->argv, (s->argc + 1) * sizeof(void *));
    102        s->argv[s->argc - 1] = val;
    103        s->argv[s->argc] = NULL;
    104    }
    105    return 0;
    106}
    107
    108/* Use strings passed via -kernel/-append to initialize semihosting.argv[] */
    109void semihosting_arg_fallback(const char *file, const char *cmd)
    110{
    111    char *cmd_token;
    112
    113    /* argv[0] */
    114    add_semihosting_arg(&semihosting, "arg", file, NULL);
    115
    116    /* split -append and initialize argv[1..n] */
    117    cmd_token = strtok(g_strdup(cmd), " ");
    118    while (cmd_token) {
    119        add_semihosting_arg(&semihosting, "arg", cmd_token, NULL);
    120        cmd_token = strtok(NULL, " ");
    121    }
    122}
    123
    124Chardev *semihosting_get_chardev(void)
    125{
    126    return semihosting.chardev;
    127}
    128
    129void qemu_semihosting_enable(void)
    130{
    131    semihosting.enabled = true;
    132    semihosting.target = SEMIHOSTING_TARGET_AUTO;
    133}
    134
    135int qemu_semihosting_config_options(const char *optarg)
    136{
    137    QemuOptsList *opt_list = qemu_find_opts("semihosting-config");
    138    QemuOpts *opts = qemu_opts_parse_noisily(opt_list, optarg, false);
    139
    140    semihosting.enabled = true;
    141
    142    if (opts != NULL) {
    143        semihosting.enabled = qemu_opt_get_bool(opts, "enable",
    144                                                true);
    145        const char *target = qemu_opt_get(opts, "target");
    146        /* setup of chardev is deferred until they are initialised */
    147        semihost_chardev = qemu_opt_get(opts, "chardev");
    148        if (target != NULL) {
    149            if (strcmp("native", target) == 0) {
    150                semihosting.target = SEMIHOSTING_TARGET_NATIVE;
    151            } else if (strcmp("gdb", target) == 0) {
    152                semihosting.target = SEMIHOSTING_TARGET_GDB;
    153            } else  if (strcmp("auto", target) == 0) {
    154                semihosting.target = SEMIHOSTING_TARGET_AUTO;
    155            } else {
    156                error_report("unsupported semihosting-config %s",
    157                             optarg);
    158                return 1;
    159            }
    160        } else {
    161            semihosting.target = SEMIHOSTING_TARGET_AUTO;
    162        }
    163        /* Set semihosting argument count and vector */
    164        qemu_opt_foreach(opts, add_semihosting_arg,
    165                         &semihosting, NULL);
    166    } else {
    167        error_report("unsupported semihosting-config %s", optarg);
    168        return 1;
    169    }
    170
    171    return 0;
    172}
    173
    174void qemu_semihosting_connect_chardevs(void)
    175{
    176    /* We had to defer this until chardevs were created */
    177    if (semihost_chardev) {
    178        Chardev *chr = qemu_chr_find(semihost_chardev);
    179        if (chr == NULL) {
    180            error_report("semihosting chardev '%s' not found",
    181                         semihost_chardev);
    182            exit(1);
    183        }
    184        semihosting.chardev = chr;
    185    }
    186}