* finish audio configuration rework * cleanup HVF stubs * remove more mentions of softmmu -----BEGIN PGP SIGNATURE----- iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmUi/kIUHHBib256aW5p QHJlZGhhdC5jb20ACgkQv/vSX3jHroOXWwf/YW16QMzqdAPVHYRf9NcCneRF16El t3lEod0q0sHhchPbh9e04aKbh+oBNeWu9sFyTl11Fwsi+DGmp/b28ziva75/4rfd h5N9aX/z2jwPqy93IwPDu3soKXCCgTK+ywtD/5GLQwBGqxs7W2xUEEb7eCnVefHa zwL3MOUqPICeqOnR1TNw9k3N3veF04D+rmchTwbAjAmx1f8EI+mK9VlGK9V8TUjP 3HjpZYJluc0a92lR5VONJ7V25QfttsjLysTgpFwVAQPS6Frzatc/hWclfLYgw9vl 2Irk83FV8gXPRl0XKNcqSDsv6h/yGP6TDFIB8QwRSRGBqIQi5aOlfBJzsQ== =qbm7 -----END PGP SIGNATURE----- Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging * util/log: re-allow switching away from stderr log file * finish audio configuration rework * cleanup HVF stubs * remove more mentions of softmmu # -----BEGIN PGP SIGNATURE----- # # iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmUi/kIUHHBib256aW5p # QHJlZGhhdC5jb20ACgkQv/vSX3jHroOXWwf/YW16QMzqdAPVHYRf9NcCneRF16El # t3lEod0q0sHhchPbh9e04aKbh+oBNeWu9sFyTl11Fwsi+DGmp/b28ziva75/4rfd # h5N9aX/z2jwPqy93IwPDu3soKXCCgTK+ywtD/5GLQwBGqxs7W2xUEEb7eCnVefHa # zwL3MOUqPICeqOnR1TNw9k3N3veF04D+rmchTwbAjAmx1f8EI+mK9VlGK9V8TUjP # 3HjpZYJluc0a92lR5VONJ7V25QfttsjLysTgpFwVAQPS6Frzatc/hWclfLYgw9vl # 2Irk83FV8gXPRl0XKNcqSDsv6h/yGP6TDFIB8QwRSRGBqIQi5aOlfBJzsQ== # =qbm7 # -----END PGP SIGNATURE----- # gpg: Signature made Sun 08 Oct 2023 15:08:50 EDT # gpg: using RSA key F13338574B662389866C7682BFFBD25F78C7AE83 # gpg: issuer "pbonzini@redhat.com" # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full] # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" [full] # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * tag 'for-upstream' of https://gitlab.com/bonzini/qemu: (25 commits) audio, qtest: get rid of QEMU_AUDIO_DRV audio: reintroduce default audio backend for VNC audio: do not use first -audiodev as default audio device audio: extend -audio to allow creating a default backend audio: extract audio_define_default audio: disable default backends if -audio/-audiodev is used audio: error hints need a trailing \n cutils: squelch compiler warnings with custom paths configure: change $softmmu to $system system: Rename softmmu/ directory as system/ meson: Rename target_softmmu_arch -> target_system_arch meson: Rename softmmu_mods -> system_mods target/i386: Rename i386_softmmu_kvm_ss -> i386_kvm_ss semihosting: Rename softmmu_FOO_user() -> uaccess_FOO_user() gdbstub: Rename 'softmmu' -> 'system' accel: Rename accel_softmmu* -> accel_system* tcg: Correct invalid mentions of 'softmmu' by 'system-mode' fuzz: Correct invalid mentions of 'softmmu' by 'system' cpu: Correct invalid mentions of 'softmmu' by 'system-mode' travis-ci: Correct invalid mentions of 'softmmu' by 'system' ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
		
			
				
	
	
		
			191 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			191 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * Semihosting configuration
 | 
						|
 *
 | 
						|
 * Copyright (c) 2015 Imagination Technologies
 | 
						|
 * Copyright (c) 2019 Linaro Ltd
 | 
						|
 *
 | 
						|
 * This controls the configuration of semihosting for all guest
 | 
						|
 * targets that support it. Architecture specific handling is handled
 | 
						|
 * in target/HW/HW-semi.c
 | 
						|
 *
 | 
						|
 * Semihosting is slightly strange in that it is also supported by some
 | 
						|
 * linux-user targets. However in that use case no configuration of
 | 
						|
 * the outputs and command lines is supported.
 | 
						|
 *
 | 
						|
 * The config module is common to all system targets however as vl.c
 | 
						|
 * needs to link against the helpers.
 | 
						|
 *
 | 
						|
 * SPDX-License-Identifier: GPL-2.0-or-later
 | 
						|
 */
 | 
						|
 | 
						|
#include "qemu/osdep.h"
 | 
						|
#include "qemu/option.h"
 | 
						|
#include "qemu/config-file.h"
 | 
						|
#include "qemu/error-report.h"
 | 
						|
#include "semihosting/semihost.h"
 | 
						|
#include "chardev/char.h"
 | 
						|
 | 
						|
QemuOptsList qemu_semihosting_config_opts = {
 | 
						|
    .name = "semihosting-config",
 | 
						|
    .merge_lists = true,
 | 
						|
    .implied_opt_name = "enable",
 | 
						|
    .head = QTAILQ_HEAD_INITIALIZER(qemu_semihosting_config_opts.head),
 | 
						|
    .desc = {
 | 
						|
        {
 | 
						|
            .name = "enable",
 | 
						|
            .type = QEMU_OPT_BOOL,
 | 
						|
        }, {
 | 
						|
            .name = "userspace",
 | 
						|
            .type = QEMU_OPT_BOOL,
 | 
						|
        }, {
 | 
						|
            .name = "target",
 | 
						|
            .type = QEMU_OPT_STRING,
 | 
						|
        }, {
 | 
						|
            .name = "chardev",
 | 
						|
            .type = QEMU_OPT_STRING,
 | 
						|
        }, {
 | 
						|
            .name = "arg",
 | 
						|
            .type = QEMU_OPT_STRING,
 | 
						|
        },
 | 
						|
        { /* end of list */ }
 | 
						|
    },
 | 
						|
};
 | 
						|
 | 
						|
typedef struct SemihostingConfig {
 | 
						|
    bool enabled;
 | 
						|
    bool userspace_enabled;
 | 
						|
    SemihostingTarget target;
 | 
						|
    char **argv;
 | 
						|
    int argc;
 | 
						|
    const char *cmdline; /* concatenated argv */
 | 
						|
} SemihostingConfig;
 | 
						|
 | 
						|
static SemihostingConfig semihosting;
 | 
						|
static const char *semihost_chardev;
 | 
						|
 | 
						|
bool semihosting_enabled(bool is_user)
 | 
						|
{
 | 
						|
    return semihosting.enabled && (!is_user || semihosting.userspace_enabled);
 | 
						|
}
 | 
						|
 | 
						|
SemihostingTarget semihosting_get_target(void)
 | 
						|
{
 | 
						|
    return semihosting.target;
 | 
						|
}
 | 
						|
 | 
						|
const char *semihosting_get_arg(int i)
 | 
						|
{
 | 
						|
    if (i >= semihosting.argc) {
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
    return semihosting.argv[i];
 | 
						|
}
 | 
						|
 | 
						|
int semihosting_get_argc(void)
 | 
						|
{
 | 
						|
    return semihosting.argc;
 | 
						|
}
 | 
						|
 | 
						|
const char *semihosting_get_cmdline(void)
 | 
						|
{
 | 
						|
    if (semihosting.cmdline == NULL && semihosting.argc > 0) {
 | 
						|
        semihosting.cmdline = g_strjoinv(" ", (gchar **)semihosting.argv);
 | 
						|
    }
 | 
						|
    return semihosting.cmdline;
 | 
						|
}
 | 
						|
 | 
						|
static int add_semihosting_arg(void *opaque,
 | 
						|
                               const char *name, const char *val,
 | 
						|
                               Error **errp)
 | 
						|
{
 | 
						|
    SemihostingConfig *s = opaque;
 | 
						|
    if (strcmp(name, "arg") == 0) {
 | 
						|
        s->argc++;
 | 
						|
        /* one extra element as g_strjoinv() expects NULL-terminated array */
 | 
						|
        s->argv = g_renew(char *, s->argv, s->argc + 1);
 | 
						|
        s->argv[s->argc - 1] = g_strdup(val);
 | 
						|
        s->argv[s->argc] = NULL;
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
/* Use strings passed via -kernel/-append to initialize semihosting.argv[] */
 | 
						|
void semihosting_arg_fallback(const char *file, const char *cmd)
 | 
						|
{
 | 
						|
    char *cmd_token;
 | 
						|
 | 
						|
    /* argv[0] */
 | 
						|
    add_semihosting_arg(&semihosting, "arg", file, NULL);
 | 
						|
 | 
						|
    /* split -append and initialize argv[1..n] */
 | 
						|
    cmd_token = strtok(g_strdup(cmd), " ");
 | 
						|
    while (cmd_token) {
 | 
						|
        add_semihosting_arg(&semihosting, "arg", cmd_token, NULL);
 | 
						|
        cmd_token = strtok(NULL, " ");
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void qemu_semihosting_enable(void)
 | 
						|
{
 | 
						|
    semihosting.enabled = true;
 | 
						|
    semihosting.target = SEMIHOSTING_TARGET_AUTO;
 | 
						|
}
 | 
						|
 | 
						|
int qemu_semihosting_config_options(const char *optstr)
 | 
						|
{
 | 
						|
    QemuOptsList *opt_list = qemu_find_opts("semihosting-config");
 | 
						|
    QemuOpts *opts = qemu_opts_parse_noisily(opt_list, optstr, false);
 | 
						|
 | 
						|
    semihosting.enabled = true;
 | 
						|
 | 
						|
    if (opts != NULL) {
 | 
						|
        semihosting.enabled = qemu_opt_get_bool(opts, "enable",
 | 
						|
                                                true);
 | 
						|
        semihosting.userspace_enabled = qemu_opt_get_bool(opts, "userspace",
 | 
						|
                                                          false);
 | 
						|
        const char *target = qemu_opt_get(opts, "target");
 | 
						|
        /* setup of chardev is deferred until they are initialised */
 | 
						|
        semihost_chardev = qemu_opt_get(opts, "chardev");
 | 
						|
        if (target != NULL) {
 | 
						|
            if (strcmp("native", target) == 0) {
 | 
						|
                semihosting.target = SEMIHOSTING_TARGET_NATIVE;
 | 
						|
            } else if (strcmp("gdb", target) == 0) {
 | 
						|
                semihosting.target = SEMIHOSTING_TARGET_GDB;
 | 
						|
            } else  if (strcmp("auto", target) == 0) {
 | 
						|
                semihosting.target = SEMIHOSTING_TARGET_AUTO;
 | 
						|
            } else {
 | 
						|
                error_report("unsupported semihosting-config %s",
 | 
						|
                             optstr);
 | 
						|
                return 1;
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            semihosting.target = SEMIHOSTING_TARGET_AUTO;
 | 
						|
        }
 | 
						|
        /* Set semihosting argument count and vector */
 | 
						|
        qemu_opt_foreach(opts, add_semihosting_arg,
 | 
						|
                         &semihosting, NULL);
 | 
						|
    } else {
 | 
						|
        error_report("unsupported semihosting-config %s", optstr);
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
/* We had to defer this until chardevs were created */
 | 
						|
void qemu_semihosting_chardev_init(void)
 | 
						|
{
 | 
						|
    Chardev *chr = NULL;
 | 
						|
 | 
						|
    if (semihost_chardev) {
 | 
						|
        chr = qemu_chr_find(semihost_chardev);
 | 
						|
        if (chr == NULL) {
 | 
						|
            error_report("semihosting chardev '%s' not found",
 | 
						|
                         semihost_chardev);
 | 
						|
            exit(1);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    qemu_semihosting_console_init(chr);
 | 
						|
}
 |